--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/client/src/ncdnodemanagerproxy.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,1235 @@
+/*
+* 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 CNcdNodeManagerProxy class
+*
+*/
+
+
+#include <e32err.h>
+
+#include "ncdnodemanagerproxy.h"
+#include "ncdnodeproxy.h"
+#include "ncdnodefolderproxy.h"
+#include "ncdbundlefolderproxy.h"
+#include "ncdsearchnodefolderproxy.h"
+#include "ncdnodeitemproxy.h"
+#include "ncdsearchnodeitemproxy.h"
+#include "catalogsclientserver.h"
+#include "ncdnodefunctionids.h"
+#include "ncdnodeclassids.h"
+#include "ncdproviderdefines.h"
+#include "ncdnodeidentifier.h"
+#include "ncdrootnodeproxy.h"
+#include "ncdpurchasedetails.h"
+#include "catalogsdebug.h"
+#include "ncdoperationmanagerproxy.h"
+#include "ncdsearchrootnodeproxy.h"
+#include "catalogsconstants.h"
+#include "catalogsutils.h"
+#include "ncdproviderproxy.h"
+#include "ncdexpirednode.h"
+#include "ncdnodesupplierproxy.h"
+#include "ncdnodeidentifiereditor.h"
+#include "ncdsearchnodebundleproxy.h"
+#include "ncdfavoritemanagerproxy.h"
+#include "ncdpanics.h"
+
+
+CNcdNodeManagerProxy* CNcdNodeManagerProxy::NewL(
+ MCatalogsClientServer& aSession,
+ TInt aHandle,
+ CNcdOperationManagerProxy& aOperationManager,
+ CNcdSubscriptionManagerProxy& aSubscriptionManager,
+ CNcdProviderProxy& aProvider )
+ {
+ CNcdNodeManagerProxy* self =
+ CNcdNodeManagerProxy::NewLC( aSession,
+ aHandle,
+ aOperationManager,
+ aSubscriptionManager,
+ aProvider );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+CNcdNodeManagerProxy* CNcdNodeManagerProxy::NewLC(
+ MCatalogsClientServer& aSession,
+ TInt aHandle,
+ CNcdOperationManagerProxy& aOperationManager,
+ CNcdSubscriptionManagerProxy& aSubscriptionManager,
+ CNcdProviderProxy& aProvider )
+ {
+ CNcdNodeManagerProxy* self =
+ new( ELeave ) CNcdNodeManagerProxy( aSession,
+ aHandle,
+ aOperationManager,
+ aSubscriptionManager,
+ aProvider );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+
+CNcdNodeManagerProxy::CNcdNodeManagerProxy(
+ MCatalogsClientServer& aSession,
+ TInt aHandle,
+ CNcdOperationManagerProxy& aOperationManager,
+ CNcdSubscriptionManagerProxy& aSubscriptionManager,
+ CNcdProviderProxy& aProvider )
+: CNcdBaseProxy( aSession, aHandle ),
+ iOperationManager( aOperationManager ),
+ iSubscriptionManager( aSubscriptionManager ),
+ iFavoriteManager( NULL ),
+ iProvider( aProvider )
+ {
+ }
+
+
+void CNcdNodeManagerProxy::ConstructL()
+ {
+ iOperationManager.SetNodeManager( this );
+
+ }
+
+
+CNcdNodeManagerProxy::~CNcdNodeManagerProxy()
+ {
+ DLTRACEIN((""));
+
+ if( iSearchRootNode )
+ {
+ // release own reference to
+ iSearchRootNode->InternalRelease();
+ }
+
+ // Release all nodes without reference count. These nodes have not
+ // been used after creation.
+ for ( TInt i = iNodeCache.Count() - 1; i >= 0; i-- )
+ {
+ if ( iNodeCache[i]->TotalRefCount() == 0 )
+ {
+ // During delete, node is removed from the array automatically.
+ // Notice that it is safe to call delete here instead of Release,
+ // because we checked the total count above. Release implementation
+ // contains DASSERT that would assert if we called Release here.
+ delete iNodeCache[i];
+ }
+ }
+
+ // For debugging purposes check if some nodes have been left hanging.
+ // All the nodes should be released before manager is deleted.
+
+ DLINFO(("Cache count: %d", iNodeCache.Count()));
+
+ #ifdef CATALOGS_BUILD_CONFIG_DEBUG
+ DLINFO(("The following nodes have not been properly released:"));
+ for ( TInt i = 0; i < iNodeCache.Count(); i++ )
+ {
+ DLINFO(( _L("MNcdNode: %x, namespace: %S, id: %S, refcount: %d"),
+ static_cast<MNcdNode*>( iNodeCache[i] ),
+ &iNodeCache[i]->Namespace(), &iNodeCache[i]->Id(),
+ iNodeCache[i]->TotalRefCount() ));
+
+ }
+ DLINFO(("release check end"));
+ #endif
+
+ DASSERT( iNodeCache.Count() == 0 );
+
+ // Close the cache.
+ iNodeCache.Close();
+
+ // Notice that the root node is also included into the cache.
+ // So, no need to delete it separately.
+
+ DLTRACEOUT((""));
+ }
+
+
+CNcdNodeProxy& CNcdNodeManagerProxy::NodeL( const CNcdNodeIdentifier& aNodeIdentifier )
+ {
+ DLTRACEIN((_L("Node ID: %S, %S, %d"),
+ &aNodeIdentifier.NodeId(),
+ &aNodeIdentifier.NodeNameSpace(),
+ aNodeIdentifier.ClientUid()));
+
+ // Check if the node proxy already exists in the cache.
+ // Every node has its own namespace and dataid.
+ // If it does, do not create it.
+
+ DLTRACE(("Node cache count: %d", iNodeCache.Count() ));
+
+ CNcdNodeProxy* node( NodeExists( aNodeIdentifier ) );
+ if ( node != NULL )
+ {
+ // Node was found. So, return it.
+ DLTRACEOUT(("Node found"));
+ return *node;
+ }
+ else if ( aNodeIdentifier.NodeNameSpace()
+ == NcdProviderDefines::KRootNodeNameSpace )
+ {
+ DLTRACE(("RootNode"));
+ // Because the node was not found from the cache,
+ // create a new node.
+ return RootNodeL();
+ }
+ else
+ {
+ DLTRACE(("Create a new node"));
+ // Because the node was not found from the cache,
+ // create a new node.
+ return CreateNodeL( aNodeIdentifier );
+ }
+ }
+
+
+CNcdRootNodeProxy& CNcdNodeManagerProxy::RootNodeL()
+ {
+ DLTRACEIN((""));
+
+ if( iRootNode == NULL )
+ {
+ DLTRACE(("Root did not exist. Create it."));
+
+ // Root does not exist. So, create it.
+
+ // First get the handle to the node of the server side.
+ // The handle is gotten from the server side nodemanager.
+ TInt rootHandle( 0 );
+ User::LeaveIfError(
+ ClientServerSession().
+ SendSync( NcdNodeFunctionIds::ENcdRootNodeHandle,
+ KNullDesC,
+ rootHandle,
+ Handle() ) );
+
+ DLTRACE(("Root handle: %d", rootHandle ));
+
+ // Now we have handle. So, create the actual root proxy.
+ // Notice that if the proxy object leaves during the construction
+ // the destructor automatically releases the handle from the server side.
+ iRootNode =
+ CNcdRootNodeProxy::NewL( ClientServerSession(),
+ rootHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+
+ // Because root node is created now, it is not in the cache yet.
+ // Put it into the cache. So, users can find the root then also
+ // by using the NodeL function.
+ iNodeCache.AppendL( iRootNode );
+ }
+
+ DLTRACEOUT((""));
+
+ return *iRootNode;
+ }
+
+CNcdSearchRootNodeProxy& CNcdNodeManagerProxy::SearchRootNodeL()
+ {
+ DLTRACEIN((""));
+
+ if( iSearchRootNode == NULL )
+ {
+ DLTRACE(("Search root did not exist. Create it."));
+
+ // Search root does not exist. So, create it.
+
+ // First get the handle to the node of the server side.
+ // The handle is gotten from the server side nodemanager.
+ TInt searchRootHandle( 0 );
+ User::LeaveIfError(
+ ClientServerSession().
+ SendSync( NcdNodeFunctionIds::ENcdSearchRootNodeHandle,
+ KNullDesC,
+ searchRootHandle,
+ Handle() ) );
+
+ DLTRACE(("Search root handle: %d", searchRootHandle ));
+
+ // Now we have handle. So, create the actual search root proxy.
+ // Notice that if the proxy object leaves during the construction
+ // the destructor automatically releases the handle from the server side.
+ iSearchRootNode =
+ CNcdSearchRootNodeProxy::NewL( ClientServerSession(),
+ searchRootHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+ // call addref to keep search root alive for search ops (search root
+ // is set as observer for them)
+ iSearchRootNode->InternalAddRef();
+ // Because search root node is created now, it is not in the cache yet.
+ // Put it into the cache. So, users can find the search root then also
+ // by using the NodeL function.
+ iNodeCache.AppendL( iSearchRootNode );
+ }
+
+ DLTRACEOUT((""));
+
+ return *iSearchRootNode;
+ }
+
+
+CNcdNodeProxy& CNcdNodeManagerProxy::CreateSchemeNodeL(
+ const CNcdNodeIdentifier& aMetadataIdentifier,
+ TNcdSchemeNodeType aType,
+ TBool aRemoveOnDisconnect,
+ TBool aForceCreate )
+ {
+ DLTRACEIN((""));
+
+ CNcdNodeProxy* node( NULL );
+
+ // Check the favorites for the given metadata and return the node which has
+ // the metadata if one exists.
+ node = iFavoriteManager->FavoriteNodeByMetaDataL( aMetadataIdentifier );
+
+ if ( node )
+ {
+ return *node;
+ }
+
+ // Node was not found from favorites.
+ if ( aForceCreate )
+ {
+ // Creation is forced, create node of correct type.
+ switch ( aType )
+ {
+ case ENcdSchemeItem:
+
+ node = &CreateTemporaryNodeItemL( aMetadataIdentifier, EFalse );
+ break;
+
+ case ENcdSchemeFolder:
+ node = &CreateTemporaryNodeFolderL( aMetadataIdentifier, EFalse );
+ break;
+
+ case ENcdSchemeBundleFolder:
+ node = &CreateTemporaryBundleFolderL( aMetadataIdentifier, EFalse );
+ break;
+
+ default:
+ NCD_ASSERT_ALWAYS( EFalse, ENcdPanicInvalidArgument );
+ break;
+ }
+ }
+ else
+ {
+ // Creation not forced, create temporary node item if metadata exists already.
+ // This leaves with KErrNotFound if metadata does not exist, thus the
+ // node cannot be created.
+ node = &CreateTemporaryNodeIfMetadataExistsL( aMetadataIdentifier );
+ }
+
+ DASSERT( node );
+
+ // Scheme nodes must be added to favourites.
+ node->AddToFavoritesL( aRemoveOnDisconnect );
+
+ DLTRACEOUT((""));
+
+ return *node;
+ }
+
+
+CNcdNodeProxy& CNcdNodeManagerProxy::CreateTemporaryNodeL(
+ const MNcdPurchaseDetails& aDetails )
+ {
+ DLTRACEIN((""));
+
+ CNcdNodeProxy* node( NULL );
+
+ CNcdNodeIdentifier* identifier(
+ CNcdNodeIdentifier::NewLC( aDetails.Namespace(),
+ aDetails.EntityId(),
+ aDetails.ServerUri(),
+ aDetails.ClientUid() ) );
+
+ if ( aDetails.ItemType() == MNcdPurchaseDetails::EItem )
+ {
+ DLINFO(("Item from purchase history"));
+ node = &CreateTemporaryNodeItemL( *identifier, ETrue );
+ }
+ else if ( aDetails.ItemType() == MNcdPurchaseDetails::EFolder )
+ {
+ DLINFO(("Folder from purchase history"));
+ node = &CreateTemporaryNodeFolderL( *identifier, ETrue );
+ }
+ else
+ {
+ DLINFO(("Unknown from purchase history"));
+ node = &CreateTemporaryOrSupplierNodeL( *identifier );
+ }
+
+ CleanupStack::PopAndDestroy( identifier );
+
+ DLTRACEOUT((""));
+
+ return *node;
+ }
+
+CNcdNodeProxy& CNcdNodeManagerProxy::CreateTemporaryNodeFolderL(
+ const CNcdNodeIdentifier& aMetadataIdentifier, TBool aCreateMetaData )
+ {
+ DLTRACEIN((_L("Metadata ID: %S, %S, %S, %d"),
+ &aMetadataIdentifier.NodeId(),
+ &aMetadataIdentifier.NodeNameSpace(),
+ &aMetadataIdentifier.ServerUri(),
+ aMetadataIdentifier.ClientUid()));
+
+ // Check if the node proxy already exists in the cache.
+ // Every node has its own namespace and dataid.
+ // If it does exist, do not create it.
+
+ // At first, try to find the node from cache by creating the node identifier
+ // from the metadata identifier.
+ CNcdNodeIdentifier* tempNodeIdentifier =
+ NcdNodeIdentifierEditor::CreateTemporaryNodeIdentifierLC( aMetadataIdentifier );
+ CNcdNodeProxy* node( NodeExists( *tempNodeIdentifier ) );
+
+ if ( node )
+ {
+ // Node was found. So, return it.
+ CleanupStack::PopAndDestroy( tempNodeIdentifier );
+ DLTRACEOUT(("Node found in cache"));
+ return *node;
+ }
+
+ // Notice that the actual node identifier is given here, instead of the
+ // metadata identifier.
+ HBufC8* nodeIdentifierData( tempNodeIdentifier->NodeIdentifierDataL() );
+ CleanupStack::PopAndDestroy( tempNodeIdentifier );
+ CleanupStack::PushL( nodeIdentifierData );
+
+ DLINFO(("Get node handle"));
+ // First get the handle to the node of the server side.
+ // The handle is gotten from the server side nodemanager.
+
+ // NOTE: The identifier may contain NULL UID here, but it will
+ // be replaced by the family id in the server side. And then
+ // the node proxy will contain the right UID when the created node is
+ // internalized during its creation.
+ TInt function = aCreateMetaData ?
+ NcdNodeFunctionIds::ENcdTemporaryNodeFolderWithMetaDataHandle :
+ NcdNodeFunctionIds::ENcdTemporaryNodeFolderHandle;
+
+ TInt nodeHandle( 0 );
+ User::LeaveIfError(
+ ClientServerSession().
+ SendSync( function,
+ *nodeIdentifierData,
+ nodeHandle,
+ Handle() ) );
+
+ DLTRACE(("Node handle: %d", nodeHandle ));
+
+ CleanupStack::PopAndDestroy( nodeIdentifierData );
+
+ // No need to check the class id here, because we requested an item
+ // node above.
+
+ node =
+ CNcdNodeFolderProxy::NewLC( ClientServerSession(),
+ nodeHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+
+ // Because we creted a new node, it should be added to the cache.
+ iNodeCache.AppendL( node );
+
+ CleanupStack::Pop( node );
+
+ DLTRACEOUT((""));
+
+ return *node;
+ }
+
+CNcdNodeProxy& CNcdNodeManagerProxy::CreateTemporaryBundleFolderL(
+ const CNcdNodeIdentifier& aMetadataIdentifier, TBool aCreateMetaData )
+ {
+ DLTRACEIN((_L("Metadata ID: %S, %S, %S, %d"),
+ &aMetadataIdentifier.NodeId(),
+ &aMetadataIdentifier.NodeNameSpace(),
+ &aMetadataIdentifier.ServerUri(),
+ aMetadataIdentifier.ClientUid()));
+
+ // Check if the node proxy already exists in the cache.
+ // Every node has its own namespace and dataid.
+ // If it does exist, do not create it.
+
+ // At first, try to find the node from cache by creating the node identifier
+ // from the metadata identifier.
+ CNcdNodeIdentifier* tempNodeIdentifier =
+ NcdNodeIdentifierEditor::CreateTemporaryNodeIdentifierLC( aMetadataIdentifier );
+ CNcdNodeProxy* node( NodeExists( *tempNodeIdentifier ) );
+
+ if ( node )
+ {
+ // Node was found. So, return it.
+ CleanupStack::PopAndDestroy( tempNodeIdentifier );
+ DLTRACEOUT(("Node found in cache"));
+ return *node;
+ }
+
+ // Notice that the actual node identifier is given here, instead of the
+ // metadata identifier.
+ HBufC8* nodeIdentifierData( tempNodeIdentifier->NodeIdentifierDataL() );
+ CleanupStack::PopAndDestroy( tempNodeIdentifier );
+ CleanupStack::PushL( nodeIdentifierData );
+
+ DLINFO(("Get node handle"));
+ // First get the handle to the node of the server side.
+ // The handle is gotten from the server side nodemanager.
+
+ // NOTE: The identifier may contain NULL UID here, but it will
+ // be replaced by the family id in the server side. And then
+ // the node proxy will contain the right UID when the created node is
+ // internalized during its creation.
+ TInt function = aCreateMetaData ?
+ NcdNodeFunctionIds::ENcdTemporaryBundleFolderWithMetaDataHandle :
+ NcdNodeFunctionIds::ENcdTemporaryBundleFolderHandle;
+
+ TInt nodeHandle( 0 );
+ User::LeaveIfError(
+ ClientServerSession().
+ SendSync( function,
+ *nodeIdentifierData,
+ nodeHandle,
+ Handle() ) );
+
+ DLTRACE(("Node handle: %d", nodeHandle ));
+
+ CleanupStack::PopAndDestroy( nodeIdentifierData );
+
+ // No need to check the class id here, because we requested a bundle folder
+ // node above.
+ node =
+ CNcdBundleFolderProxy::NewLC( ClientServerSession(),
+ nodeHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+
+ // Because we creted a new node, it should be added to the cache.
+ iNodeCache.AppendL( node );
+
+ CleanupStack::Pop( node );
+
+ DLTRACEOUT((""));
+
+ return *node;
+ }
+
+
+CNcdNodeProxy& CNcdNodeManagerProxy::CreateTemporaryNodeItemL(
+ const CNcdNodeIdentifier& aMetadataIdentifier,
+ TBool aCreateMetaData )
+ {
+ DLTRACEIN((_L("Metadata ID: %S, %S, %S, %d"),
+ &aMetadataIdentifier.NodeId(),
+ &aMetadataIdentifier.NodeNameSpace(),
+ &aMetadataIdentifier.ServerUri(),
+ aMetadataIdentifier.ClientUid()));
+
+ // Check if the node proxy already exists in the cache.
+ // Every node has its own namespace and dataid.
+ // If it does exist, do not create it.
+
+ // At first, try to find the node from cache by creating the node identifier
+ // from the metadata identifier.
+ CNcdNodeIdentifier* tempNodeIdentifier =
+ NcdNodeIdentifierEditor::CreateTemporaryNodeIdentifierLC( aMetadataIdentifier );
+ CNcdNodeProxy* node( NodeExists( *tempNodeIdentifier ) );
+
+ if ( node )
+ {
+ // Node was found. So, return it.
+ CleanupStack::PopAndDestroy( tempNodeIdentifier );
+ DLTRACEOUT(("Node found in cache"));
+ return *node;
+ }
+
+ // Notice that the actual node identifier is given here, instead of the
+ // metadata identifier.
+ HBufC8* nodeIdentifierData( tempNodeIdentifier->NodeIdentifierDataL() );
+ CleanupStack::PopAndDestroy( tempNodeIdentifier );
+ CleanupStack::PushL( nodeIdentifierData );
+
+ DLINFO(("Get node handle"));
+ // First get the handle to the node of the server side.
+ // The handle is gotten from the server side nodemanager.
+
+ // NOTE: The identifier may contain NULL UID here, but it will
+ // be replaced by the family id in the server side. And then
+ // the node proxy will contain the right UID when the created node is
+ // internalized during its creation.
+ TInt function = aCreateMetaData ?
+ NcdNodeFunctionIds::ENcdTemporaryNodeItemWithMetaDataHandle :
+ NcdNodeFunctionIds::ENcdTemporaryNodeItemHandle;
+
+ TInt nodeHandle( 0 );
+ User::LeaveIfError(
+ ClientServerSession().
+ SendSync( function,
+ *nodeIdentifierData,
+ nodeHandle,
+ Handle() ) );
+
+ DLTRACE(("Node handle: %d", nodeHandle ));
+
+ CleanupStack::PopAndDestroy( nodeIdentifierData );
+
+ // No need to check the class id here, because we requested an item
+ // node above.
+
+ node =
+ CNcdNodeItemProxy::NewLC( ClientServerSession(),
+ nodeHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+
+ // Because we creted a new node, it should be added to the cache.
+ iNodeCache.AppendL( node );
+
+ CleanupStack::Pop( node );
+
+ DLTRACEOUT((""));
+
+ return *node;
+ }
+
+
+CNcdNodeProxy& CNcdNodeManagerProxy::CreateTemporaryNodeIfMetadataExistsL(
+ const CNcdNodeIdentifier& aMetadataIdentifier )
+ {
+ DLTRACEIN((_L("Metadata ID: %S, %S, %S, %d"),
+ &aMetadataIdentifier.NodeId(),
+ &aMetadataIdentifier.NodeNameSpace(),
+ &aMetadataIdentifier.ServerUri(),
+ aMetadataIdentifier.ClientUid()));
+
+ CNcdNodeIdentifier* tempNodeIdentifier =
+ NcdNodeIdentifierEditor::CreateTemporaryNodeIdentifierLC( aMetadataIdentifier );
+
+ // Check if the node proxy already exists in the cache.
+ // Every node has its own namespace and dataid.
+ // If it does exist, do not create it.
+ CNcdNodeProxy* node( NodeExists( *tempNodeIdentifier ) );
+ if ( node )
+ {
+ // Node was found. So, return it.
+ CleanupStack::PopAndDestroy( tempNodeIdentifier );
+ DLTRACEOUT(("Node found in cache"));
+ return *node;
+ }
+
+ // Node was not found from the cache. So, new node proxy has to be created.
+
+ // Notice that the actual node identifier is given here for the server, instead of the
+ // metadata identifier.
+ HBufC8* nodeIdentifierData( tempNodeIdentifier->NodeIdentifierDataL() );
+ CleanupStack::PushL( nodeIdentifierData );
+
+ DLINFO(("Create temporary if metadata exists"));
+
+ // This is the output value from SendSync. It tells whether the node was created in server side.
+ // It will be ETrue also when the node existed there already.
+ TBool isCreated( EFalse );
+
+ // NOTE: The identifier may contain NULL UID here, but it will
+ // be replaced by the family id in the server side. And then
+ // the node proxy will contain the right UID when the created node is
+ // internalized during its creation.
+ // This will create the temporary node in server side if the metadata exists there already.
+ // So, it can be requested next when the node proxy will be created.
+ User::LeaveIfError(
+ ClientServerSession().
+ SendSync( NcdNodeFunctionIds::ENcdCreateTemporaryNodeIfMetadataExists,
+ *nodeIdentifierData,
+ isCreated,
+ Handle() ) );
+
+ CleanupStack::PopAndDestroy( nodeIdentifierData );
+
+ if ( isCreated )
+ {
+ // The node was created above in the server side if it did not
+ // already exist. So, we can be sure that we get the node below.
+ // NodeL knows how to create the correct node and inserts it to the cache.
+ // So, use that function here.
+ // Notice, that there is no need to use ReplaceCacheNodeL here because the
+ // supplier node can use it itself when the correct node data has been loaded
+ // from the web.
+ node = &NodeL( *tempNodeIdentifier );
+ CleanupStack::PopAndDestroy( tempNodeIdentifier );
+ }
+ else
+ {
+ User::Leave( KErrNotFound );
+ }
+
+ DLTRACEOUT(("metadata was found and temporary node created"));
+
+ return *node;
+ }
+
+
+CNcdNodeProxy& CNcdNodeManagerProxy::CreateTemporaryOrSupplierNodeL(
+ const CNcdNodeIdentifier& aMetadataIdentifier )
+ {
+ DLTRACEIN((_L("Metadata ID: %S, %S, %S, %d"),
+ &aMetadataIdentifier.NodeId(),
+ &aMetadataIdentifier.NodeNameSpace(),
+ &aMetadataIdentifier.ServerUri(),
+ aMetadataIdentifier.ClientUid()));
+
+ // Notice that the supplier node and the temporary node use same identifiers
+ // but only one version should exist at a time.
+
+ CNcdNodeIdentifier* tempNodeIdentifier =
+ NcdNodeIdentifierEditor::CreateTemporaryNodeIdentifierLC( aMetadataIdentifier );
+
+ // Check if the node proxy already exists in the cache.
+ // Every node has its own namespace and dataid.
+ // If it does exist, do not create it.
+ CNcdNodeProxy* node( NodeExists( *tempNodeIdentifier ) );
+ if ( node )
+ {
+ // Node was found. So, return it.
+ CleanupStack::PopAndDestroy( tempNodeIdentifier );
+ DLTRACEOUT(("Node found in cache"));
+ return *node;
+ }
+
+ // Node was not found from the cache. So, new node proxy has to be created.
+
+ // Notice that the actual node identifier is given here for the server, instead of the
+ // metadata identifier.
+ HBufC8* nodeIdentifierData( tempNodeIdentifier->NodeIdentifierDataL() );
+ CleanupStack::PushL( nodeIdentifierData );
+
+ DLINFO(("Create temporary or supplier node proxy"));
+
+ // tmpNum is not used for anything, but give the SendSync at least some parameter.
+ TInt tmpNum( 0 );
+
+ // NOTE: The identifier may contain NULL UID here, but it will
+ // be replaced by the family id in the server side. And then
+ // the node proxy will contain the right UID when the created node is
+ // internalized during its creation.
+ // This will create the supplier or temporary node in server side. So, it can be
+ // requested next when the node proxy will be created.
+ User::LeaveIfError(
+ ClientServerSession().
+ SendSync( NcdNodeFunctionIds::ENcdCreateTemporaryOrSupplierNode,
+ *nodeIdentifierData,
+ tmpNum,
+ Handle() ) );
+
+ CleanupStack::PopAndDestroy( nodeIdentifierData );
+
+ // The node was created above in the server side if it did not
+ // already exist. So, we can be sure that we get the node below.
+ // NodeL knows how to create the correct node and inserts it to the cache.
+ // So, use that function here.
+ // Notice, that there is no need to use ReplaceCacheNodeL here because the
+ // supplier node can use it itself when the correct node data has been loaded
+ // from the web.
+ node = &NodeL( *tempNodeIdentifier );
+
+ CleanupStack::PopAndDestroy( tempNodeIdentifier );
+
+ DLTRACEOUT((""));
+
+ return *node;
+ }
+
+
+CNcdNodeProxy& CNcdNodeManagerProxy::ReplaceCacheNodeL( const CNcdNodeIdentifier& aNodeIdentifier )
+ {
+ DLTRACEIN((""))
+
+ // Remove the node that has the given identifier from the cache.
+ // Notice, that the node is now left hanging. And, it will be just deleted
+ // when the user releases it. Also, notice that when the node is deleted,
+ // CNcdNodeManager::NodeDeleted() will be called but it does not matter because the
+ // comparisons in that function are done by using pointers, not identifiers.
+ for ( TInt i = 0; i < iNodeCache.Count(); ++i )
+ {
+ // Because the UID may be set NULL for an identifier and because the
+ // UID should always be same for all the nodes in this application,
+ // the UID is not included when comparing node identifiers here.
+ if ( iNodeCache[ i ]->NodeIdentifier().
+ Equals( aNodeIdentifier, ETrue, ETrue, EFalse, EFalse ) )
+ {
+ iNodeCache.Remove( i );
+ }
+ }
+
+ DLTRACEOUT((""));
+
+ // This will also insert the new node into the cache.
+ // Let the node call leave if something goes wrong. Actually,
+ // at least some node should be found if one version of the node with the
+ // given identifier alreay exists in the server side.
+ // This call may also leave if we are out of memory. In that case just leave.
+ // Do not try to set the removed node back to the array. When memory is released.
+ // It can be requested from the server side normally later.
+ return NodeL( aNodeIdentifier );
+ }
+
+
+CNcdNodeProxy* CNcdNodeManagerProxy::NodeExists( const CNcdNodeIdentifier& aNodeIdentifier ) const
+ {
+ DLTRACEIN((""));
+ for ( TInt i = 0; i < iNodeCache.Count(); ++i )
+ {
+ // Because the UID may be set NULL for an identifier and because the
+ // UID should always be same for all the nodes in this application,
+ // the UID is not included when comparing node identifiers here.
+ if ( iNodeCache[ i ]->NodeIdentifier().
+ Equals( aNodeIdentifier, ETrue, ETrue, EFalse, EFalse ) )
+ {
+ // The node has already been created
+ // because the link ids matched.
+ // Return the old node.
+ DLTRACE(("node found"));
+ return iNodeCache[ i ];
+ }
+ }
+ DLTRACE(("node not found"));
+ return NULL;
+ }
+
+
+void CNcdNodeManagerProxy::NodeDeleted( CNcdNodeProxy* aNode )
+ {
+ DLTRACEIN(("Node Deleted"));
+
+ CNcdNodeProxy* root( iRootNode );
+ CNcdNodeProxy* searchRoot( iSearchRootNode );
+ if( root == aNode )
+ {
+ DLTRACE(("Deleted root node"));
+ // Because the root node is deleted. Set the pointer value to null.
+ iRootNode = NULL;
+ }
+ else if( searchRoot == aNode )
+ {
+ DLTRACE(("Deleted search node"));
+ // Because the search root node is deleted. Set the pointer value to
+ // null.
+ iSearchRootNode = NULL;
+ }
+
+ // Remove node from the cache because it will be or has been deleted.
+ for ( TInt i = 0; i < iNodeCache.Count(); ++i )
+ {
+ if( aNode == iNodeCache[ i ] )
+ {
+ DLTRACE(("Removing from cache"));
+ // Remove node from the array.
+ iNodeCache.Remove( i );
+ break;
+ }
+ }
+ }
+
+
+void CNcdNodeManagerProxy::InternalizeRelatedNodesL( CNcdNodeProxy& aNode ) const
+ {
+ DLTRACEIN((""));
+
+ // First internalize the given node
+ aNode.InternalizeL();
+
+ // Then check if there is some other nodes to internalize.
+
+ // Get the metadata identifier of the given node.
+ CNcdNodeIdentifier* paramMetaIdentifier(
+ NcdNodeIdentifierEditor::CreateMetaDataIdentifierLC(
+ aNode.NodeIdentifier() ) );
+ CNcdNodeIdentifier* metaIdentifier( NULL );
+ CNcdNodeProxy* node( NULL );
+
+ // Check if related nodes are found from the cache.
+ for ( TInt i = 0; i < iNodeCache.Count(); ++i )
+ {
+ node = iNodeCache[ i ];
+ metaIdentifier =
+ NcdNodeIdentifierEditor::CreateMetaDataIdentifierLC(
+ node->NodeIdentifier() );
+
+ // Because given node has already been internalized, there is no need to redo it
+ // here. But, internalize all related nodes.
+ // When identifiers are compared, compare only id and namespace. Omit comparison
+ // of URI and UID. UID may be NULL if the node has not been internalized before.
+ if ( &aNode != node
+ && paramMetaIdentifier->Equals( *metaIdentifier,
+ ETrue, ETrue, EFalse, EFalse ) )
+ {
+ DLINFO(("Related node found. Internalize."));
+ node->InternalizeL();
+ }
+
+ CleanupStack::PopAndDestroy( metaIdentifier );
+ metaIdentifier = NULL;
+ }
+
+ CleanupStack::PopAndDestroy( paramMetaIdentifier );
+ DLTRACEOUT((""));
+ }
+
+
+CNcdSubscriptionManagerProxy&
+ CNcdNodeManagerProxy::SubscriptionManager() const
+ {
+ return iSubscriptionManager;
+ }
+
+void CNcdNodeManagerProxy::SetFavoriteManager(
+ CNcdFavoriteManagerProxy& aFavoriteManager )
+ {
+ iFavoriteManager = &aFavoriteManager;
+ }
+
+void CNcdNodeManagerProxy::ClearSearchResultsL()
+ {
+ DLTRACEIN((""));
+ TInt err = KErrNone;
+ User::LeaveIfError( ClientServerSession().SendSync(
+ NcdNodeFunctionIds::ENcdClearSearchResults,
+ KNullDesC,
+ err,
+ Handle() ) );
+ DLTRACEOUT(( "err = %d", err ));
+ }
+
+
+TBool CNcdNodeManagerProxy::IsCapabilitySupportedL( const CNcdNodeIdentifier& aNode,
+ const TDesC& aCapability )
+ {
+ DLTRACEIN((""));
+ CBufBase* sendBuffer = CBufFlat::NewL( KBufExpandSize );
+ CleanupStack::PushL( sendBuffer );
+ RBufWriteStream stream( *sendBuffer );
+ CleanupClosePushL( stream );
+
+ aNode.ExternalizeL( stream );
+ ExternalizeDesL( aCapability, stream );
+
+ TPtrC8 sendPtr( sendBuffer->Ptr( 0 ) );
+
+ CleanupStack::PopAndDestroy( &stream );
+ TBool isCapabilitySupported = EFalse;
+
+ User::LeaveIfError( ClientServerSession().SendSync(
+ NcdNodeFunctionIds::ENcdIsCapabilitySupported,
+ sendPtr,
+ isCapabilitySupported,
+ Handle() ) );
+
+ CleanupStack::PopAndDestroy( sendBuffer );
+ return isCapabilitySupported;
+ }
+
+
+void CNcdNodeManagerProxy::HandleExpiredNodesL(
+ RPointerArray< CNcdExpiredNode >& aExpiredNodes )
+ {
+ DLTRACEIN((""));
+ RCatalogsArray<MNcdNode> expiredNodeArray;
+ CleanupClosePushL( expiredNodeArray );
+ for( TInt i = 0 ; i < aExpiredNodes.Count() ; i++ )
+ {
+ CNcdNodeProxy* node = NodeExists( aExpiredNodes[i]->NodeIdentifier() );
+ if( node )
+ {
+ DLTRACE(("Node existed"));
+ // Perhaps errors should not be ignored?
+ TRAP_IGNORE( node->InternalizeL() );
+ if ( aExpiredNodes[i]->ForceUpdate() )
+ {
+ DLTRACE(("Force update set, add to array"));
+ node->AddRef();
+ expiredNodeArray.AppendL( node );
+ }
+ }
+ }
+ if( expiredNodeArray.Count() > 0 )
+ {
+ DLTRACE(("Send force update nodes to provider"));
+ iProvider.ExpirationCallback( expiredNodeArray );
+ }
+ CleanupStack::PopAndDestroy( &expiredNodeArray );
+ }
+
+
+CNcdProviderProxy& CNcdNodeManagerProxy::Provider() const
+ {
+ return iProvider;
+ }
+
+/*
+CNcdNodeProxy& CNcdNodeManagerProxy::CreateSchemeNodeL(
+ const CNcdNodeIdentifier& aMetadataIdentifier,
+ TInt aFunctionId )
+ {
+ DLTRACEIN((_L("ID: %S, %S, %d"),
+ &aMetadataIdentifier.NodeId(),
+ &aMetadataIdentifier.NodeNameSpace(),
+ aMetadataIdentifier.ClientUid()));
+
+ // Check that the root is not in an unitialized state.
+ // Scheme should be created only if the root has been initialized before.
+ // Because the root is only used here internally, there is no need to increase
+ // the reference count.
+ CNcdRootNodeProxy& root( RootNodeL() );
+ if ( root.State() == MNcdNode::EStateNotInitialized )
+ {
+ DLERROR(("Root was not initialized before creation of scheme!"));
+ DASSERT( EFalse );
+ User::Leave( KErrNotReady );
+ }
+
+ CNcdNodeIdentifier* nodeIdentifier =
+ NcdNodeIdentifierEditor::CreateNodeIdentifierLC(
+ RootNodeL().NodeIdentifier(),
+ aMetadataIdentifier );
+
+ // Check if the node proxy already exists in the cache.
+ // Every node has its own namespace and dataid.
+ // If it does exist, do not create it.
+
+ CNcdNodeProxy* node( NodeExists( *nodeIdentifier ) );
+ if ( node != NULL )
+ {
+ // Node was found. So, return it.
+ CleanupStack::PopAndDestroy( nodeIdentifier );
+ DLTRACEOUT(("Node found"));
+ return *node;
+ }
+
+ HBufC8* nodeIdentifierData( nodeIdentifier->NodeIdentifierDataL() );
+ CleanupStack::PushL( nodeIdentifierData );
+
+ // NOTE: The identifier may contain NULL UID here, but it will
+ // be replaced by the family id in the server side. And then
+ // the node proxy will contain the right UID when the created node is
+ // internalized during its creation.
+
+ // tmpNum will not be used for anything. It is just given as a dummy parameter for
+ // the session request.
+ TInt tmpNum( 0 );
+ User::LeaveIfError(
+ ClientServerSession().
+ SendSync( aFunctionId,
+ *nodeIdentifierData,
+ tmpNum,
+ Handle() ) );
+
+ CleanupStack::PopAndDestroy( nodeIdentifierData );
+
+ // The node was created above in the server side if it did not
+ // already exist. So, we can be sure that we get the node below.
+ // NodeL knows how to create the correct node and inserts it to the cache.
+ // So, use that function here.
+ node = &NodeL( *nodeIdentifier );
+
+ CleanupStack::PopAndDestroy( nodeIdentifier );
+
+ // Update root node by calling internalization because scheme nodes will
+ // be added to the root node also.
+ RootNodeL().InternalizeL();
+
+ DLTRACEOUT((""));
+
+ return *node;
+ }
+*/
+
+ CNcdNodeProxy& CNcdNodeManagerProxy::CreateNodeL( const CNcdNodeIdentifier& aNodeIdentifier )
+ {
+ DLTRACEIN((""));
+
+ CNcdNodeProxy* node( NULL );
+
+ HBufC8* nodeIdentifierData( aNodeIdentifier.NodeIdentifierDataL() );
+ CleanupStack::PushL( nodeIdentifierData );
+
+ DLINFO(("Get node handle"));
+ // First get the handle to the node of the server side.
+ // The handle is gotten from the server side nodemanager.
+
+ // NOTE: The identifier may contain NULL UID here, but it will
+ // be replaced by the family id in the server side. And then
+ // the node proxy will contain the right UID when the created node is
+ // internalized during its creation.
+
+ TInt nodeHandle( 0 );
+ User::LeaveIfError(
+ ClientServerSession().
+ SendSync( NcdNodeFunctionIds::ENcdNodeHandle,
+ *nodeIdentifierData,
+ nodeHandle,
+ Handle() ) );
+
+ DLTRACE(("Node handle: %d", nodeHandle ));
+
+ CleanupStack::PopAndDestroy( nodeIdentifierData );
+
+
+ // Next, check the type of the node. So, we can create
+ // right type of the proxy.
+ TInt classId( 0 );
+ TInt classIdError =
+ ClientServerSession().
+ SendSync( NcdNodeFunctionIds::ENcdClassId,
+ KNullDesC,
+ classId,
+ nodeHandle );
+ if ( classIdError != KErrNone )
+ {
+ // Because we can not create the proxy object for some reason,
+ // release the handle.
+ TInt tmpNum( 0 );
+ ClientServerSession().
+ SendSync( NcdNodeFunctionIds::ENcdRelease,
+ KNullDesC,
+ tmpNum,
+ Handle() );
+
+ // For debuggin reasons.
+ DLERROR(("Class id error"));
+ DASSERT( EFalse );
+
+ User::Leave( classIdError );
+ }
+
+ // Create the node according to the class id
+ // Notice that if the proxy object leaves during the construction
+ // the destructor automatically releases the handle from the server side.
+ switch( classId )
+ {
+ case NcdNodeClassIds::ENcdFolderNodeClassId:
+ node =
+ CNcdNodeFolderProxy::NewLC( ClientServerSession(),
+ nodeHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+ break;
+
+ case NcdNodeClassIds::ENcdTransparentFolderNodeClassId:
+ // The transparent folder is handled in the proxy
+ // side as a normal folder.
+ node =
+ CNcdNodeFolderProxy::NewLC( ClientServerSession(),
+ nodeHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+ break;
+
+ case NcdNodeClassIds::ENcdBundleFolderNodeClassId:
+ node =
+ CNcdBundleFolderProxy::NewLC( ClientServerSession(),
+ nodeHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+ break;
+
+ case NcdNodeClassIds::ENcdSearchFolderNodeClassId:
+ node =
+ CNcdSearchNodeFolderProxy::NewLC( ClientServerSession(),
+ nodeHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+ break;
+
+ case NcdNodeClassIds::ENcdItemNodeClassId:
+ node =
+ CNcdNodeItemProxy::NewLC( ClientServerSession(),
+ nodeHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+ break;
+
+ case NcdNodeClassIds::ENcdSearchItemNodeClassId:
+ node =
+ CNcdSearchNodeItemProxy::NewLC( ClientServerSession(),
+ nodeHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+ break;
+
+ case NcdNodeClassIds::ENcdSearchRootNodeClassId:
+ node =
+ CNcdSearchRootNodeProxy::NewLC( ClientServerSession(),
+ nodeHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+ break;
+
+
+ case NcdNodeClassIds::ENcdSupplierNodeClassId:
+ {
+ node = CNcdNodeSupplierProxy::NewLC( ClientServerSession(),
+ nodeHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+
+ break;
+ }
+
+ case NcdNodeClassIds::ENcdSearchBundleNodeClassId:
+ {
+ node =
+ CNcdSearchNodeBundleProxy::NewLC( ClientServerSession(),
+ nodeHandle,
+ *this,
+ iOperationManager,
+ *iFavoriteManager );
+ break;
+ }
+
+ default:
+ // classId is not recognized
+ // So, node is left NULL
+ DLERROR(("Node class type was not recognized!"));
+ // For testing purposes assert here
+ DASSERT( EFalse );
+ break;
+ }
+
+ // Because we creted a new node, it should be added to the cache.
+ iNodeCache.AppendL( node );
+
+ CleanupStack::Pop( node );
+ DLTRACEOUT((""));
+ return *node;
+ }