ncdengine/provider/client/src/ncdnodefolderproxy.cpp
changeset 0 ba25891c3a9e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/client/src/ncdnodefolderproxy.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,407 @@
+/*
+* 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 CNcdNodeFolderProxy class implementation
+*
+*/
+
+
+#include "ncdnodefolderproxy.h"
+#include "ncdnodemetadataproxy.h"
+#include "catalogsclientserver.h"
+#include "ncdnodemanagerproxy.h"
+#include "ncdoperationmanagerproxy.h"
+#include "ncdnodeidentifier.h"
+#include "catalogsdebug.h"
+#include "ncdnodefunctionids.h"
+#include "ncdnodeclassids.h"
+#include "catalogsinterfaceidentifier.h"
+#include "ncdloadnodeoperationproxy.h"
+#include "ncdnodesearchimpl.h"
+#include "catalogsutils.h"
+#include "ncdchildentity.h"
+#include "ncdproviderdefines.h"
+#include "ncdnodeuricontentproxy.h"
+#include "ncdcapabilities.h"
+#include "ncdnodeseenfolderproxy.h"
+#include "ncderrors.h"
+
+CNcdNodeFolderProxy::CNcdNodeFolderProxy( MCatalogsClientServer& aSession,
+                                          TInt aHandle,
+                                          CNcdNodeManagerProxy& aNodeManager,
+                                          CNcdOperationManagerProxy& aOperationManager,
+                                          CNcdFavoriteManagerProxy& aFavoriteManager ) 
+: CNcdNodeProxy( aSession, aHandle, aNodeManager, aOperationManager, aFavoriteManager )
+    {
+    }
+
+
+void CNcdNodeFolderProxy::ConstructL()
+    {
+    CNcdNodeProxy::ConstructL(); 
+
+    // Add the interface information to the list
+    MNcdNodeContainer* container( this );
+    AddInterfaceL( 
+        CCatalogsInterfaceIdentifier::NewL( container, this, MNcdNodeContainer::KInterfaceUid ) );                    
+    }
+
+
+CNcdNodeFolderProxy* CNcdNodeFolderProxy::NewL( MCatalogsClientServer& aSession,
+                                                TInt aHandle,
+                                                CNcdNodeManagerProxy& aNodeManager,
+                                                CNcdOperationManagerProxy& aOperationManager,
+                                                CNcdFavoriteManagerProxy& aFavoriteManager )
+    {
+    CNcdNodeFolderProxy* self = 
+        CNcdNodeFolderProxy::NewLC(
+            aSession, aHandle, aNodeManager, aOperationManager, aFavoriteManager );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+CNcdNodeFolderProxy* CNcdNodeFolderProxy::NewLC( MCatalogsClientServer& aSession,
+                                                 TInt aHandle,
+                                                 CNcdNodeManagerProxy& aNodeManager,
+                                                 CNcdOperationManagerProxy& aOperationManager,
+                                                 CNcdFavoriteManagerProxy& aFavoriteManager )
+    {
+    CNcdNodeFolderProxy* self = 
+        new( ELeave ) CNcdNodeFolderProxy(
+            aSession, aHandle, aNodeManager, aOperationManager, aFavoriteManager );  
+    // Using PushL because the object does not have any references yet
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+
+CNcdNodeFolderProxy::~CNcdNodeFolderProxy()
+    {
+    // Remove interfaces implemented by this class from the interface list.
+    // So, the interface list is up to date when this class object is deleted.
+    RemoveInterface( MNcdNodeContainer::KInterfaceUid );
+    RemoveInterface( MNcdNodeSearch::KInterfaceUid );
+
+    // 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 iSearch;
+    iSearch = NULL;
+    
+    delete iNodeSeenFolder;
+    iNodeSeenFolder = NULL;
+    
+    iChildren.ResetAndDestroy();
+    }
+
+
+
+
+TInt CNcdNodeFolderProxy::ExpectedChildCount() const
+    {
+    return iExpectedChildCount;
+    }
+
+
+MNcdLoadNodeOperation* CNcdNodeFolderProxy::LoadL(
+    MNcdLoadNodeOperationObserver& aObserver ) 
+    {
+    DLTRACEIN((_L("This ns: %S, id: %S"), &Namespace(), &Id() ));    
+    return CNcdNodeProxy::LoadL( aObserver );
+    }
+
+
+TInt CNcdNodeFolderProxy::ChildCount() const
+    {
+    return iExpectedChildCount;
+    }
+
+
+MNcdNode* CNcdNodeFolderProxy::ChildL( TInt aIndex )
+    {
+    DLTRACEIN(( _L("This parent: %S, %S"), &Namespace(), &Id(), aIndex ));
+    DLINFO(("aIndex = %d, expected childcount= %d, real child count = %d",
+        aIndex, iExpectedChildCount, iChildren.Count() ));
+        
+    if ( aIndex < 0 || aIndex >= iExpectedChildCount )
+        {
+        // Nothing to be done 
+        DLERROR(( "Index error. expected child count: %d Given index: %d", 
+                  iExpectedChildCount, aIndex ));
+        DASSERT( EFalse );
+        User::Leave( KErrArgument );   
+        }
+        
+    // search for a child with given index
+    const CNcdNodeIdentifier* child = NULL;
+    for( TInt i = 0 ; i < iChildren.Count() ; i++ )
+        {
+        if ( iChildren[i]->Index() == aIndex )
+            {
+            child = &iChildren[i]->Identifier();
+            }
+        else if ( iChildren[i]->Index() > aIndex )
+            {
+            // no sense in searching further
+            break;
+            }
+        }
+
+    if( child == NULL )
+        {
+        return NULL;
+        }
+    
+    MNcdNode* node( NULL );
+    
+    TRAPD( err, node = &NodeManager().NodeL( *child ) );    
+
+    if ( err == KErrNotFound ) 
+        {
+        return NULL;
+        }
+
+    User::LeaveIfError( err );
+    
+    // Increase the reference counter by one
+    node->AddRef();
+    
+    DLTRACEOUT((""));
+
+    return node;
+    }
+    
+    
+MNcdLoadNodeOperation* CNcdNodeFolderProxy::LoadChildrenL( TInt aIndex, 
+                                                           TInt aSize,
+                                                           TNcdChildLoadMode aMode,
+                                                           MNcdLoadNodeOperationObserver& aObserver )
+    {
+    DLTRACEIN(("aIndex: %d, aSize: %d, expected child count: %d, load mode: %d",
+        aIndex, aSize, iExpectedChildCount, aMode ));
+
+    if ( aSize < 1 
+         || aIndex < 0 
+         || ( aMode == ELoadMetadata 
+              && aSize != KMaxTInt 
+              && aIndex + aSize > ChildCount() ) )
+        {
+        // Nothing to be done 
+        DLERROR(( "Argument error. ChildCount: %d Given index: %d, size: %d",
+                  ChildCount(), aIndex, aSize ));
+        User::Leave( KErrArgument );
+        }
+
+    if ( aSize == KMaxTInt )
+        {
+        // Because aSize is KMaxTInt, reduce it by the aIndex value.
+        // This way we will not have possible overload if aIndex is later added
+        // to the aSize value. It does not really matter what the aSize value is
+        // after this. KMaxTInt is so great value, that in all the cases the server
+        // request should give all the required items.
+        aSize -= aIndex;
+        DLINFO(("aSize was KMaxTInt. Reduced by index: %d", aSize));
+        }
+
+    DLTRACE(( _L("Node: %S, %S"), &Namespace(), &Id() ));
+    
+    CNcdLoadNodeOperationProxy* operation = 
+        OperationManager().CreateLoadNodeOperationL( 
+            *this, ETrue, aSize, aIndex, 1, aMode );
+
+    if ( !operation )
+        {
+        DLTRACEOUT(("NULL"));     
+        return NULL;
+        }
+
+    operation->AddObserverL( this );
+    operation->AddObserverL( &aObserver );
+
+    DLTRACEOUT((""));        
+
+    return operation;
+    }
+    
+TNcdContainerType CNcdNodeFolderProxy::ContainerType() const
+    {
+    if ( IsRemote() ) 
+        {
+        return ECatalog;
+        }
+    else 
+        {
+        return EFolder;
+        }
+    }
+
+void CNcdNodeFolderProxy::OperationComplete( 
+    MNcdLoadNodeOperation& /*aOperation*/, TInt aError )
+    {
+    DLTRACEIN(( "Error: %d", aError ));
+    
+    if ( aError == KErrNone || aError == KNcdErrorSomeCatalogsFailedToLoad )
+        {
+        // update proxy's status from the server
+        TRAP_IGNORE( InternalizeL() );
+        }
+    }
+
+void CNcdNodeFolderProxy::InternalizeL()
+    {
+    DLTRACEIN((""));
+
+    // First call the parent internalizator. So, all the parent stuff will
+    // be initialized before folder specific data.
+    CNcdNodeProxy::InternalizeL();
+
+    // Add the search interface because it is availabe for all the folders
+    // that have at least one child.
+    
+    // check that is search supported for this node
+    TBool isSearchSupported = IsSearchSupportedL();
+        
+    DLINFO(( "isSearchSupported: %d, child count: %d", isSearchSupported, 
+        ChildCount() ));
+    if ( isSearchSupported )
+        {
+        DLTRACE(("add search interface"));
+        if ( iSearch == NULL )
+            {
+            // Create new search because old one did not exist.
+            // Notice that the creation adds the interface to the node interface list
+            // automatically.
+            iSearch = CNcdNodeSearch::NewL( *this, OperationManager() );    
+            }
+        }
+    else
+        {
+        DLTRACE(("remove search interface"));        
+        delete iSearch;
+        iSearch = NULL;
+        }
+        
+    InternalizeNodeSeenFolderL();        
+                   
+    DLTRACEOUT((""));
+    }
+
+
+void CNcdNodeFolderProxy::InternalizeNodeDataL( RReadStream& aStream )
+    {
+    DLTRACEIN((""));
+    
+    // First internalize parent data
+    CNcdNodeProxy::InternalizeNodeDataL( aStream );
+
+    // Get the children data here.
+
+    DLTRACE(("Handle children"));
+
+    // Clear the buffer because new childs will be appended
+    iChildren.ResetAndDestroy();
+    
+    TInt childrenCount( aStream.ReadInt32L() );
+    DLTRACE(("Children: %d", childrenCount ));
+
+    TInt classObjectType( NcdNodeClassIds::ENcdNullObjectClassId );
+
+    for ( TInt i = 0; i < childrenCount; ++i )
+        {
+        // This is safe casting because enum is same as TInt
+        classObjectType = 
+            static_cast<NcdNodeClassIds::TNcdNodeClassId>(aStream.ReadInt32L());
+        if ( NcdNodeClassIds::ENcdChildEntityClassId == classObjectType )
+            {
+            CNcdChildEntity* childEntity = CNcdChildEntity::NewLC( aStream );
+            iChildren.AppendL( childEntity );
+            CleanupStack::Pop( childEntity );            
+            DLINFO((_L("Added child, id: %S, array index: %d, real index: %d"),
+            &childEntity->Identifier().NodeId(), i, childEntity->Index() ));
+            }
+        else
+            {
+            // For debug purposes
+            DLERROR(("Wrong class id"));
+            DASSERT( EFalse );
+
+            // Wrong kind of class object info
+            User::Leave( KErrCorrupt );
+            }
+        }
+        
+    // Show node info here, after the internalization has been done.        
+    DLTRACEOUT(( _L("Node: %S, %S, %d"), 
+                 &Namespace(), &Id(), NodeIdentifier().ClientUid().iUid ));
+    }
+
+
+void CNcdNodeFolderProxy::InternalizeNodeLinkDataL( RReadStream& aStream )
+    {
+    DLTRACEIN(( _L("Node: %S, %S"), &Namespace(), &Id() ));
+    
+    // First internalize parent data
+    CNcdNodeProxy::InternalizeNodeLinkDataL( aStream );
+
+    // Then, set the data for this class object
+    
+    iExpectedChildCount = aStream.ReadInt32L();
+
+    DLTRACEOUT((""));
+    }
+
+TBool CNcdNodeFolderProxy::IsSearchSupportedL()
+    {
+    DLTRACEIN((""));
+    // check if this node has search capability set
+    return NodeManager().IsCapabilitySupportedL( NodeIdentifier(),
+        NcdCapabilities::KSearch );
+    }
+    
+
+void CNcdNodeFolderProxy::InternalizeNodeSeenFolderL() 
+    {
+    DLTRACEIN((""));
+    
+    if ( iNodeSeenFolder )
+        {
+        iNodeSeenFolder->InternalizeL();
+        }
+    else 
+        {
+        // Create the object.  
+        // Get the handle at first.
+        TInt handle( 0 );
+        User::LeaveIfError(
+            ClientServerSession().SendSync(
+                NcdNodeFunctionIds::ENcdNodeSeenFolderHandle,
+                KNullDesC(),
+                handle,
+                Handle() ) );
+        
+        DLINFO(( "handle: %d", handle ));
+       
+        iNodeSeenFolder = CNcdNodeSeenFolderProxy::NewL(
+            ClientServerSession(), handle, *this );
+        }
+    }
+                    
+