diff -r 000000000000 -r ba25891c3a9e ncdengine/provider/client/src/ncdnodeproxy.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ncdengine/provider/client/src/ncdnodeproxy.cpp Thu Dec 17 08:51:10 2009 +0200 @@ -0,0 +1,829 @@ +/* +* 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 CNcdNodeProxy class implementation +* +*/ + + +#include "ncdnodeproxy.h" +#include "ncdrootnodeproxy.h" +#include "ncdnodecontainer.h" +#include "ncdnodefolderproxy.h" +#include "ncdnodemetadataproxy.h" +#include "ncdnodeuserdataproxy.h" +#include "ncdoperationmanagerproxy.h" +#include "ncdloadnodeoperationproxy.h" +#include "catalogsclientserver.h" +#include "ncdnodeidentifier.h" +#include "ncdnodefunctionids.h" +#include "ncdnodeclassids.h" +#include "catalogsinterfaceidentifier.h" +#include "catalogsdebug.h" +#include "catalogsutils.h" +#include "ncdnodemanagerproxy.h" +#include "ncdfavoritemanagerproxy.h" +#include "ncdquery.h" +#include "ncdnodedisclaimerproxy.h" +#include "ncdnodefavorite.h" +#include "ncdnodeidentifiereditor.h" +#include "ncdnodeseenproxy.h" + + +CNcdNodeProxy::CNcdNodeProxy( MCatalogsClientServer& aSession, + TInt aHandle, + CNcdNodeManagerProxy& aNodeManager, + CNcdOperationManagerProxy& aOperationManager, + CNcdFavoriteManagerProxy& aFavoriteManager ) +: CNcdInterfaceBaseProxy( aSession, aHandle, NULL ), + iNodeManager( aNodeManager ), + iOperationManager( aOperationManager ), + iFavoriteManager( aFavoriteManager ) + { + } + + +void CNcdNodeProxy::ConstructL( ) + { + DLTRACEIN(("this-ptr as MNcdNode: %X", static_cast( this ))); + + // Register the interfaces of this object + MNcdNode* node( this ); + AddInterfaceL( + CCatalogsInterfaceIdentifier::NewL( node, this, MNcdNode::KInterfaceUid ) ); + + // Make sure that at least some values are inserted to the link descriptors. + // So, the references returned from functions of this class will contain at + // least something. + iTimestamp = KNullDesC().AllocL(); + iCatalogSourceName = KNullDesC().AllocL(); + iExpiredTime = 0; + + // Get the data from the server side. + // It may be possible that actually not much is received + // because the node may be in uninitialized state. + // But at least the namespace and id information should be gotten. + TRAPD( trapError, InternalizeL() ); + + // This node can not exist if the identifier data is not set. + // So, if node identifier is not set this should leave and + // prevent the creation of the node. + if ( iNodeIdentifier == NULL ) + { + User::LeaveIfError( trapError ); + } + + // Also make sure that parent identifier is set at least to empty value + if ( iParentIdentifier == NULL ) + { + // If we have to set the parent identifier here, it means that + // the node link was not set yet. + // If node link was set, then the parent id was also set to correct value. + // And, then this value should not be set here. + iParentIdentifier = CNcdNodeIdentifier::NewL(); + } + + if ( iRealParentIdentifier == NULL ) + { + iRealParentIdentifier = CNcdNodeIdentifier::NewL(); + } + + DLTRACEOUT(("")); + } + + +CNcdNodeProxy::~CNcdNodeProxy() + { + DLTRACEIN(("this-ptr: %x", this)); + // Because this object is deleted. Remove the interfaces from the + // interface list. + RemoveInterface( MNcdNode::KInterfaceUid ); + RemoveInterface( MNcdNodeChildOfTransparent::KInterfaceUid ); + RemoveInterface( MNcdNodeFavorite::KInterfaceUid ); + + // Inform node manager that this node is under deletion. + iNodeManager.NodeDeleted( this ); + + delete iNodeIdentifier; + iNodeIdentifier = NULL; + + // Delete link data + + delete iCatalogSourceName; + iCatalogSourceName = NULL; + + delete iParentIdentifier; + iParentIdentifier = NULL; + + delete iRealParentIdentifier; + iRealParentIdentifier = NULL; + + delete iTimestamp; + iTimestamp = NULL; + + + // Delete the objects that are owned by this class and provide functionality + // through the api. + // Notice that the api-objects are Released (not deleted) from the UI side. + // The node owns the data and the reference counter of the node keeps + // track of the api objects it owns. When the reference counter of the node + // reaches zero, it means that nobody is using the node or the classes owned + // by the node. If somebody is using the object owned by the node, the reference + // counter can not be zero until everything is released. + // Thus, the node may delete the data here. + + delete iMetadata; + iMetadata = NULL; + + delete iNodeSeen; + iNodeSeen = NULL; + DLTRACEOUT(("this-ptr: %x", this)); + } + + + +CNcdNodeIdentifier& CNcdNodeProxy::NodeIdentifier() const + { + return *iNodeIdentifier; + } + + +CNcdNodeManagerProxy& CNcdNodeProxy::NodeManager() const + { + return iNodeManager; + } + + +CNcdOperationManagerProxy& CNcdNodeProxy::OperationManager() const + { + return iOperationManager; + } + + +CNcdNodeMetadataProxy* CNcdNodeProxy::Metadata() const + { + //DASSERT( iMetadata ); + return iMetadata; + } + + +void CNcdNodeProxy::InternalizeL() + { + DLTRACEIN(("this-ptr: %x", this)); + DPROFILING_BEGIN( x ); + HBufC8* data( NULL ); + + // Because we do not know the exact size of the data id, 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::ENcdInternalize, + KNullDesC8, + data, + Handle(), + 0 ) ); + + if ( data == NULL ) + { + User::Leave( KErrNotFound ); + } + + CleanupStack::PushL( data ); + + DLINFO(( "Ncd node internalize data length: %d", data->Length() )); + + // Read the data from the stream and insert it to the memeber variables + RDesReadStream stream( *data ); + CleanupClosePushL( stream ); + + // Let this leave. If the node can not internalize itself, then + // something is really badly wrong. In this case this node should + // even be created. So, if this is called from ContstructL it should + // most likely to leave also. + InternalizeNodeDataL( stream ); + + // Closes the stream + CleanupStack::PopAndDestroy( &stream ); + CleanupStack::PopAndDestroy( data ); + + + // The node data was internalized. + + // Next, internalize the link data if it exists. + DLINFO(("Internalize node proxy link")); + InternalizeLinkL(); + + + // TRAP the functions after this. So, all the existing new interfaces + // may be added to the interface list. + + // Also, metadata may be ready for initialization. + DLINFO(("Internalize node proxy metadata")); + TRAP_IGNORE( InternalizeMetadataL() ); + + // Internalize node seen proxy. + DLINFO(("Internalize node seen")); + InternalizeNodeSeenL(); + + // Install the MNcdNodeFavorite interface if the same metadata is favorite already. + if ( iFavoriteManager.IsFavoriteL( *iNodeIdentifier ) ) + { + MNcdNodeFavorite* node( this ); + AddInterfaceL( + CCatalogsInterfaceIdentifier::NewL( node, this, MNcdNodeFavorite::KInterfaceUid ) ); + } + DPROFILING_END( x ); + DLTRACEOUT(("")); + } + + +void CNcdNodeProxy::AddToFavoritesL( TBool aRemoveOnDisconnect ) + { + DLTRACEIN(("aRemoveOnDisconnect: %d", aRemoveOnDisconnect)); + if ( !iFavoriteManager.IsFavoriteL( *iNodeIdentifier ) ) + { + iFavoriteManager.AddToFavoritesL( *iNodeIdentifier, aRemoveOnDisconnect ); + } + + // Register the MNcdNodeFavorite interface. + MNcdNodeFavorite* node( this ); + AddInterfaceL( + CCatalogsInterfaceIdentifier::NewL( node, this, MNcdNodeFavorite::KInterfaceUid ) ); + } + + + +// MNcdNode functions + + +MNcdNode::TState CNcdNodeProxy::State() const + { + DLTRACEIN((_L("Node namespace=%S, id=%S"), &Namespace(), &Id() )); + + // Check if the link handle has been set, which means that also + // link data has been internalized. Also, check if the metadata + // exists, which means that metadata has also been internalized. + if ( LinkHandleSet() + && iMetadata != NULL ) + { + DLINFO(("State was initialized")); + // If state was initialized we have to check if the state + // has acutally expired already + TTime now; + now.HomeTime(); + + DLINFO(("now time: %d", now.Int64() )); + DLINFO(("expired time: %d", ExpiredTime().Int64() )); + + // We can just compare the times here. Server side + // inserts the maximum value for the expired time if the + // protocol has set never expire value for the validity delta. + if ( now > ExpiredTime() ) + { + DLTRACEOUT(("Expired")); + return MNcdNode::EStateExpired; + } + + DLTRACEOUT(("Initialized")); + return MNcdNode::EStateInitialized; + } + else + { + // Node has not been initialized. + DLTRACEOUT(("Not initialized")); + return MNcdNode::EStateNotInitialized; + } + } + + +const TDesC& CNcdNodeProxy::Id() const + { + DLTRACEIN(("")); + return iNodeIdentifier->NodeId(); + } + +const TDesC& CNcdNodeProxy::Namespace() const + { + DLTRACEIN(("")); + return iNodeIdentifier->NodeNameSpace(); + } + +const TDesC& CNcdNodeProxy::CatalogSourceName() const + { + DLTRACEIN(("")); + return *iCatalogSourceName; + } + +MNcdNodeContainer* CNcdNodeProxy::ParentL() const + { + DLTRACEIN(("")); + + if( iParentIdentifier == NULL + || iParentIdentifier->ContainsEmptyFields() ) + { + DLTRACEOUT(("Parent identifier was not set. Return NULL")); + return NULL; + } + else + { + DLINFO(("Parent identifier was set. Get the parent")); + + // This always gives reference to the node + // We use pointer instead of reference afterwards. + // NodeL leaves if the node was not found. + MNcdNode* parent = &iNodeManager.NodeL( *iParentIdentifier ); + + DLINFO(("Parent was gotten")); + + // This should always give something because parent is always container. + // Notice, that the query interface increases the reference count automatically. + MNcdNodeContainer* container = parent->QueryInterfaceL(); + + DLTRACEOUT(( _L("Return parent container interface: %X"), container )); + + return container; + } + } + +MNcdLoadNodeOperation* CNcdNodeProxy::LoadL( MNcdLoadNodeOperationObserver& aObserver ) + { + DLTRACEIN(("")); + + CNcdLoadNodeOperationProxy* operation( NULL ); + + operation = + iOperationManager.CreateLoadNodeOperationL( *this ); + + operation->AddObserverL( this ); + operation->AddObserverL( &aObserver ); + + DLTRACEOUT(("")); + + return operation; + } + +RCatalogsArray CNcdNodeProxy::OperationsL() const + { + DLTRACEIN(("this: %x, iMetadata: %x", this, iMetadata )); + RCatalogsArray operations; + CleanupClosePushL( operations ); + + if ( iMetadata ) + { + // Get the original array and insert its content to catalogs array. + // Also, increase the reference counter for the items. + const RPointerArray& origArray = iOperationManager.Operations(); + MNcdOperation* oper( NULL ); + MNcdNode* node( NULL ); + + CNcdNodeMetadataProxy* metadata( NULL ); + DLTRACE(("Getting metaidentifier")); + const CNcdNodeIdentifier& metadataId( iMetadata->Identifier() ); + + DLTRACE(("Origarray.count: %d", origArray.Count() )); + for ( TInt i = 0; i < origArray.Count(); ++i ) + { + oper = origArray[ i ]; + DLTRACE(("oper: %x", oper)); + // Notice that node ref count is increased. So, release it when done. + node = oper->Node(); + if ( node ) + { + CleanupReleasePushL( *node ); + + // Compare metadatas + metadata = static_cast( node )->Metadata(); + DLTRACE(("Metadata: %x", metadata)); + if ( metadata && metadata->Identifier().Equals( metadataId ) ) + { + DLTRACE(("Appending to ops array")); + operations.AppendL( oper ); + oper->AddRef(); + } + + CleanupStack::PopAndDestroy( node ); + } + } + } + + CleanupStack::Pop( &operations ); + + DLTRACEOUT(( "" )); + return operations; + } + + +void CNcdNodeProxy::AddToFavoritesL() + { + AddToFavoritesL( EFalse ); + } + + +// MNcdLoadNodeOperationObserver + + +void CNcdNodeProxy::NodesUpdated( MNcdLoadNodeOperation& /*aOperation*/, + RCatalogsArray< MNcdNode >& aNodes ) + { + + for ( TInt i = 0 ; i < aNodes.Count() ; i++ ) + { + // Should the node provide its own function instead of API interface + // that can be called when node/nodes should be updated. Operations know + // the node proxy object so they could use the function directly instead + // of using more restricted API interfaces. Then, no casting would be required + // here... + CNcdNodeProxy* node = static_cast(aNodes[i]); + TRAP_IGNORE( node->InternalizeL() ); + /*// make sure that this node is a child of this node + TIdentityRelation relation(CNcdNodeIdentifier::Equals); + if ( iChildren.Find( node->NodeIdentifier(), relation ) == KErrNotFound ) + { + + }*/ + } + + // This function of the observer interface does not need to do anythin here. + } + +void CNcdNodeProxy::QueryReceived( MNcdLoadNodeOperation& /*aOperation*/, + MNcdQuery* aQuery ) + { + // This function of the observer interface does not need to do anythin here. + aQuery->Release(); + } + +void CNcdNodeProxy::OperationComplete( MNcdLoadNodeOperation& /*aOperation*/, + TInt /*aError*/ ) + { + DLTRACEIN(("")); + DLINFO(("Nothing done.")); + DLTRACEOUT(("")); + } + + +// MNcdNodeChildOfTransparent + +MNcdNode* CNcdNodeProxy::TransparentParentL() const + { + DLTRACEIN(("")); + DASSERT( iRealParentIdentifier ); + DASSERT( !iRealParentIdentifier->ContainsEmptyFields() ); + + MNcdNode* parent( NULL ); + TRAPD( err, parent = &NodeManager().NodeL( *iRealParentIdentifier ) ); + + if ( err == KErrNotFound ) + { + return NULL; + } + + User::LeaveIfError( err ); + + parent->AddRef(); + return parent; + } + + +// MNcdNodeFavorite + +void CNcdNodeProxy::RemoveFromFavoritesL() + { + DLTRACEIN(("")); + iFavoriteManager.RemoveFromFavoritesL( *iNodeIdentifier ); + RemoveInterface( MNcdNodeFavorite::KInterfaceUid ); + } + + +void CNcdNodeProxy::SetDisclaimerL( MNcdNode* aDisclaimerOwner ) + { + DLTRACEIN(("")); + iFavoriteManager.SetNodeDisclaimerL( *iNodeIdentifier, aDisclaimerOwner ); + } + + +MNcdQuery* CNcdNodeProxy::DisclaimerL() const + { + DLTRACEIN(("")); + MNcdQuery* disclaimer = iFavoriteManager.NodeDisclaimerL( *iNodeIdentifier ); + if ( disclaimer ) + { + disclaimer->AddRef(); + } + return disclaimer; + } + + +// Other functions + +TBool CNcdNodeProxy::LinkHandleSet() const + { + return iLinkHandleSet; + } + +TInt CNcdNodeProxy::LinkHandleL() const + { + if( !iLinkHandleSet ) + { + // Link handle has not been set + User::Leave( KErrNotReady ); + } + + return iLinkHandle; + } + +void CNcdNodeProxy::SetLinkHandle( TInt aHandle ) + { + iLinkHandle = aHandle; + iLinkHandleSet = ETrue; + } + +TTime CNcdNodeProxy::ExpiredTime() const + { + return iExpiredTime; + } + +CNcdNodeIdentifier* CNcdNodeProxy::ParentIdentifier() const + { + return iParentIdentifier; + } + +TBool CNcdNodeProxy::IsRemote() const + { + return iRemoteFlag; + } + + +// ======== FUNCTIONS FOR NODE INTERNALIZATION ======== + + +void CNcdNodeProxy::InternalizeLinkL() + { + DLTRACEIN(("")); + + // Get the handle for the link data + if ( !LinkHandleSet() ) + { + DLINFO(("Link handle was not set. Set it now.")); + TInt linkHandle( 0 ); + + // Leave for example by using KErrNotFound if the link did not exist. + User::LeaveIfError( + ClientServerSession(). + SendSync( NcdNodeFunctionIds::ENcdLinkHandle, + KNullDesC, + linkHandle, + Handle() ) ); + + // Link existed. So, we got the handle. + DLINFO(("Handle: %i", linkHandle)); + SetLinkHandle( linkHandle ); + } + + HBufC8* data( NULL ); + // Because we do not know the exact size of the data id, 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::ENcdInternalize, + KNullDesC8, + data, + LinkHandleL(), + 0 ) ); + + if ( data == NULL ) + { + DLINFO(("Received link data was NULL")); + User::Leave( KErrNotFound ); + } + + CleanupStack::PushL( data ); + + DLINFO(( "Received link data length: %d", data->Length() )); + + // Read the data from the stream and insert it to the memeber variables + RDesReadStream stream( *data ); + CleanupClosePushL( stream ); + + InternalizeNodeLinkDataL( stream ); + + // Closes the stream + CleanupStack::PopAndDestroy( &stream ); + CleanupStack::PopAndDestroy( data ); + + DLTRACEOUT(("")); + } + + +void CNcdNodeProxy::InternalizeNodeDataL( RReadStream& aStream ) + { + DLTRACEIN(("")); + + // Read the class id of the node + // (not actually needed here at the moment but may be used to check if the + // data is of the right type...) + aStream.ReadInt32L(); + + // No need to put the newIdentifier into the cleanup stack because this + // function will not leave before inserting the value to the member variable. + CNcdNodeIdentifier* newIdentifier = CNcdNodeIdentifier::NewL( aStream ); + delete iNodeIdentifier; + iNodeIdentifier = newIdentifier; + + DLTRACEOUT(("")); + } + +void CNcdNodeProxy::InternalizeNodeLinkDataL( RReadStream& aStream ) + { + DLTRACEIN(("")); + + HBufC* tmpTimeStamp( NULL ); + HBufC* tmpCatalogSourceName( NULL ); + TBool tmpRemoteFlag( EFalse ); + TInt64 tmpExpiredTime( 0 ); + CNcdNodeIdentifier* tmpParentIdentifier( NULL ); + CNcdNodeIdentifier* tmpRealParentIdentifier( NULL ); + + // Read the class id of the link + TInt tmpInt = aStream.ReadInt32L(); + DLINFO(("Classid: %d", tmpInt)); + + if ( tmpInt != NcdNodeClassIds::ENcdNullObjectClassId ) + { + + InternalizeDesL( tmpTimeStamp, aStream ); + CleanupStack::PushL( tmpTimeStamp ); + DLINFO(( _L("timestamp: %S"), tmpTimeStamp )); + + InternalizeDesL( tmpCatalogSourceName, aStream ); + CleanupStack::PushL( tmpCatalogSourceName ); + DLINFO(( _L("catalogsource: %S"), tmpCatalogSourceName )); + + tmpRemoteFlag = aStream.ReadInt32L(); + DLINFO((_L("remote flag: %d"), tmpRemoteFlag)); + + aStream >> tmpExpiredTime; + DLINFO(("expired time: %d", tmpExpiredTime )); + + tmpParentIdentifier = CNcdNodeIdentifier::NewLC( aStream ); + tmpRealParentIdentifier = CNcdNodeIdentifier::NewLC( aStream ); + } + else + { + tmpTimeStamp = KNullDesC().AllocLC(); + tmpCatalogSourceName = KNullDesC().AllocLC(); + } + + + // Now we can be sure that this function will not leave. + // So it is safe to set the values for the member variables. + delete iRealParentIdentifier; + iRealParentIdentifier = tmpRealParentIdentifier; + if ( tmpRealParentIdentifier ) + { + CleanupStack::Pop( tmpRealParentIdentifier ); + } + + delete iParentIdentifier; + iParentIdentifier = tmpParentIdentifier; + if( tmpParentIdentifier ) + { + CleanupStack::Pop( tmpParentIdentifier ); + if ( !iRealParentIdentifier->Equals( *iParentIdentifier ) ) + { + // Must be child of transparent node since real parent identifier is + // different. Register the MNcdNodeChildOfTransparent interface. + DLINFO(("child of transparent")); + MNcdNodeChildOfTransparent* interface( this ); + AddInterfaceL( + CCatalogsInterfaceIdentifier::NewL( + interface, this, MNcdNodeChildOfTransparent::KInterfaceUid ) ); + } + } + + if ( !iRealParentIdentifier || iRealParentIdentifier->Equals( *iParentIdentifier ) ) + { + // Real parent in engine is same as in proxy -> parent is not transparent -> + // remove the MNcdNodeChildOfTransparent interface. + RemoveInterface( MNcdNodeChildOfTransparent::KInterfaceUid ); + } + + iExpiredTime = tmpExpiredTime; + + iRemoteFlag = tmpRemoteFlag; + + delete iCatalogSourceName; + iCatalogSourceName = tmpCatalogSourceName; + CleanupStack::Pop( tmpCatalogSourceName ); + + delete iTimestamp; + iTimestamp = tmpTimeStamp; + CleanupStack::Pop( tmpTimeStamp ); + + DLTRACEOUT(("")); + } + + +void CNcdNodeProxy::InternalizeMetadataL() + { + DLTRACEIN(("")); + + if ( iMetadata == NULL ) + { + DLINFO(("Metadata did not exist")); + + // Check if the metadata exists in the server side and update the information + TInt metadataHandle( 0 ); + + TInt handleError = + ClientServerSession(). + SendSync( NcdNodeFunctionIds::ENcdMetadataHandle, + KNullDesC, + metadataHandle, + Handle() ); + + if ( handleError == KErrNotFound ) + { + DLINFO(("Metadata did not exist in server side")); + + // Because metadata did not exist in the server side + // Nothing to do here. + return; + } + else + { + // If error occurred then leave + User::LeaveIfError( handleError ); + } + + DLINFO(("Metadata existed")); + + // Now we can create the metadata object + // Notice that this object will add its own interfaces to the + // querylist when the object is created. + // Also, notice that if the proxy object leaves during the construction + // the destructor automatically releases the handle from the server side. + iMetadata = CNcdNodeMetadataProxy::NewL( ClientServerSession(), + metadataHandle, + *this ); + // Metadata ref counter is not increased here. + // So, it will be zero until somebody asks for the metadata. + // If the Release is called and + // when the reference counter reaches zero, this node which + // acts as parent will be deleted. The destructor of this + // node will delete the metadata because this node owns it. + } + else + { + // Notice that that if the proxy object was created above, + // it internalizes itself during construction. So, call + // the internalize here only if the object was not constructed + // above. + // Proxy object existed. + // So, internalize it with new data. + iMetadata->InternalizeL(); + } + + DLTRACEOUT(("")); + } + + +void CNcdNodeProxy::InternalizeNodeSeenL() + { + DLTRACEIN(("")); + if ( iNodeSeen ) + { + // The proxy can internalize its state itself. + iNodeSeen->InternalizeL(); + } + else + { + // The proxy object not created yet, create it. + DLINFO(("Node seen did not exist")); + TInt nodeSeenHandle( 0 ); + + User::LeaveIfError( + ClientServerSession().SendSync( + NcdNodeFunctionIds::ENcdNodeSeenHandle, + KNullDesC, + nodeSeenHandle, + Handle() ) ); + + // Got the handle, create the proxy object. The proxy object internalizes itself + // in construction. + iNodeSeen = CNcdNodeSeenProxy::NewL( + ClientServerSession(), nodeSeenHandle, *this ); + } + }