ncdengine/provider/server/src/ncdsearchoperationimpl.cpp
changeset 0 ba25891c3a9e
child 24 84a16765cd86
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 <badesca.h>
       
    20 #include <s32mem.h>
       
    21 #include <limits.h>
       
    22 
       
    23 #include "ncdsearchoperationimpl.h"
       
    24 #include "ncdoperationfunctionids.h"
       
    25 #include "catalogsbasemessage.h"
       
    26 #include "catalogshttpsession.h"
       
    27 #include "catalogshttpoperation.h"
       
    28 #include "catalogshttpconfig.h"
       
    29 #include "catalogsdebug.h"
       
    30 #include "catalogsbigdes.h"
       
    31 #include "ncdrequestgenerator.h"
       
    32 #include "catalogsaccesspointmanager.h"
       
    33 
       
    34 #include "ncdrequestbase.h"
       
    35 #include "ncdrequestbrowsesearch.h"
       
    36 #include "ncdrequestconfiguration.h"
       
    37 #include "ncd_pp_itemref.h"
       
    38 #include "ncd_pp_folderref.h"
       
    39 #include "ncd_pp_dataentity.h"
       
    40 #include "ncd_pp_error.h"
       
    41 // remove these
       
    42 #include "ncd_pp_itemrefimpl.h"
       
    43 #include "ncd_pp_folderrefimpl.h"
       
    44 #include "ncd_pp_dataentityimpl.h"
       
    45 #include "ncd_pp_datablock.h"
       
    46 //
       
    47 #include "ncdprotocolutils.h"
       
    48 #include "ncdprotocol.h"
       
    49 #include "ncdprotocolimpl.h"
       
    50 #include "ncdparser.h"
       
    51 #include "ncdnodemanager.h"
       
    52 #include "ncdproviderdefines.h"
       
    53 #include "ncdnodeidentifier.h"
       
    54 #include "ncdnodeclassids.h"
       
    55 #include "ncdnodefolder.h"
       
    56 #include "ncdoperationobserver.h"
       
    57 #include "catalogssession.h"
       
    58 #include "ncdnodeimpl.h"
       
    59 #include "ncdnodelink.h"
       
    60 #include "ncdqueryimpl.h"
       
    61 #include "catalogsutils.h"
       
    62 #include "ncd_cp_query.h"
       
    63 #include "ncdnodemetadata.h"
       
    64 #include "ncdnodemetadataimpl.h"
       
    65 #include "ncderrors.h"
       
    66 #include "ncdoperationremovehandler.h"
       
    67 #include "ncdstoragedescriptordataitem.h"
       
    68 #include "ncdnodeiconimpl.h"
       
    69 #include "ncdnodelink.h"
       
    70 #include "catalogsconstants.h"
       
    71 #include "ncdnodeclassids.h"
       
    72 #include "ncdnodecontentinfoimpl.h"
       
    73 #include "ncditempurpose.h"
       
    74 #include "ncdutils.h"
       
    75 #include "ncdsearchnodefolder.h"
       
    76 #include "ncdnodeclassids.h"
       
    77 #include "ncdnodefactory.h"
       
    78 #include "ncdnodeidentifiereditor.h"
       
    79 #include "ncdsearchnodefolder.h"
       
    80 #include "ncdcapabilities.h"
       
    81 #include "ncdsearchnodebundle.h"
       
    82 #include "ncdchildentity.h"
       
    83 
       
    84 
       
    85 //_LIT8(KRequestBody, "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <preminetRequest xmlns=\"http://nokia.com/preminet/protocol/v/2/0\"  xmlns:cp=\"http://nokia.com/preminet/protocol/configuration/v/1/0\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"2.0\" namespace=\"http://lynx.ionific.com:9086/ntp-cgw/catalogs\"> <configuration> <client> <cp:software version=\"3.2\" type=\"S60\"/> </client> </configuration> <search> <entity xsi:type=\"Folder\" id=\"cgw_normal\" timestamp=\"2007-12-17T09:30:47.0Z\"/> <entityFilter subscribableContent=\"false\"> <keywords all=\"true\" caseSensitive=\"false\"> <keyword exclude=\"false\">a</keyword> </keywords> <reviewScore>1</reviewScore> </entityFilter> <responseFilter structureDepth=\"2\" metadataDepth=\"2\" metadataPerLevel=\"5\" pageStart=\"2\" pageSize=\"2\"/> </search> </preminetRequest>");
       
    86 
       
    87 // ======== MEMBER FUNCTIONS ========
       
    88 
       
    89 
       
    90 // ---------------------------------------------------------------------------
       
    91 // ?description_if_needed
       
    92 // ---------------------------------------------------------------------------
       
    93 //
       
    94 CNcdSearchOperation* CNcdSearchOperation::NewL(    
       
    95     const CNcdNodeIdentifier& aNodeIdentifier,
       
    96     const CNcdNodeIdentifier& aParentIdentifier,
       
    97     const CNcdSearchFilter& aSearchFilter,
       
    98     TNcdResponseFilterParams aFilterParams,    
       
    99     CNcdGeneralManager& aGeneralManager,
       
   100     MCatalogsHttpSession& aHttpSession,
       
   101     MNcdOperationRemoveHandler* aRemoveHandler,
       
   102     MNcdOperationQueue* aOperationQueue,
       
   103     MCatalogsSession& aSession,
       
   104     TBool aLoadChildren,
       
   105     TNcdChildLoadMode aMode,
       
   106     TInt aRecursionLevels,
       
   107     TBool aIsSubOperation )
       
   108     {
       
   109     CNcdSearchOperation* self = CNcdSearchOperation::NewLC(
       
   110         aNodeIdentifier,
       
   111         aParentIdentifier,
       
   112         aSearchFilter,
       
   113         aFilterParams,        
       
   114         aGeneralManager,        
       
   115         aHttpSession,        
       
   116         aRemoveHandler,
       
   117         aOperationQueue,        
       
   118         aSession,
       
   119         aLoadChildren,
       
   120         aMode,
       
   121         aRecursionLevels,
       
   122         aIsSubOperation );
       
   123     CleanupStack::Pop( self );
       
   124     return self;
       
   125     }
       
   126 
       
   127 
       
   128 // ---------------------------------------------------------------------------
       
   129 // ?description_if_needed
       
   130 // ---------------------------------------------------------------------------
       
   131 //
       
   132 CNcdSearchOperation* CNcdSearchOperation::NewLC(
       
   133     const CNcdNodeIdentifier& aNodeIdentifier,
       
   134     const CNcdNodeIdentifier& aParentIdentifier,
       
   135     const CNcdSearchFilter& aSearchFilter,
       
   136     TNcdResponseFilterParams aFilterParams,
       
   137     CNcdGeneralManager& aGeneralManager,    
       
   138     MCatalogsHttpSession& aHttpSession,
       
   139     MNcdOperationRemoveHandler* aRemoveHandler,
       
   140     MNcdOperationQueue* aOperationQueue,
       
   141     MCatalogsSession& aSession,
       
   142     TBool aLoadChildren,
       
   143     TNcdChildLoadMode aMode,
       
   144     TInt aRecursionLevels,
       
   145     TBool aIsSubOperation )
       
   146     {
       
   147     CNcdSearchOperation* self =
       
   148         new( ELeave ) CNcdSearchOperation( aFilterParams, aMode,
       
   149             aLoadChildren, aGeneralManager, aHttpSession,
       
   150             aRemoveHandler, aOperationQueue, aSession, aRecursionLevels,
       
   151             aIsSubOperation );
       
   152     CleanupClosePushL( *self );
       
   153     self->ConstructL( aNodeIdentifier, aParentIdentifier, aSearchFilter );
       
   154     return self;
       
   155     }
       
   156     
       
   157 // ---------------------------------------------------------------------------
       
   158 // ?description_if_needed
       
   159 // ---------------------------------------------------------------------------
       
   160 //
       
   161 CNcdSearchOperation::~CNcdSearchOperation()
       
   162     {    
       
   163     DLTRACEIN((""));
       
   164     delete iSearchFilter;
       
   165     iRemoteFoldersChildOfTransparent.ResetAndDestroy();
       
   166     }
       
   167 
       
   168 // ---------------------------------------------------------------------------
       
   169 // ?implementation_description
       
   170 // ---------------------------------------------------------------------------
       
   171 //
       
   172 void CNcdSearchOperation::FolderRefL(
       
   173     MNcdPreminetProtocolFolderRef* aData )
       
   174     {
       
   175     DLTRACEIN(("%X",aData));
       
   176 
       
   177     if ( aData == NULL )
       
   178         {
       
   179         return;
       
   180         }
       
   181     TRAPD( err, DoFolderRefL( aData ) );
       
   182 
       
   183     if( err != KErrNone )
       
   184         {
       
   185         Cancel();
       
   186         iError = err;
       
   187         iLoadNodeState = EFailed;
       
   188         }
       
   189     RunOperation();
       
   190     
       
   191     }
       
   192 
       
   193 void CNcdSearchOperation::DoFolderRefL( MNcdPreminetProtocolFolderRef* aData )    
       
   194     {
       
   195     DLTRACEIN((""));        
       
   196 
       
   197     // Normal PushL causes USER 42
       
   198     CleanupDeletePushL( aData );
       
   199     
       
   200     DLTRACE(( _L("folder id=%S, ns=%S"), 
       
   201         &aData->Id(), &aData->Namespace() ));
       
   202     DLTRACE(( _L("Parent id=%S, ns=%S"), 
       
   203         &aData->ParentId(), &aData->ParentNamespace() ));
       
   204 
       
   205 #ifdef CATALOGS_BUILD_CONFIG_DEBUG    
       
   206     if ( iParentIdentifier ) 
       
   207         {
       
   208         DLNODEID( (*iParentIdentifier) );
       
   209         }
       
   210 #endif
       
   211     
       
   212     TBool nodeAdded = EFalse;
       
   213     
       
   214     // This will contain pointer to the iNodeIdentifier or to the iParentIdentifier
       
   215     // So, we will know in the end which one is the parent of the current data item.
       
   216     // Do not delete this in the end because this just points to the member
       
   217     // variables.
       
   218     CNcdNodeIdentifier* tmpSearchParentIdentifier( iParentIdentifier );
       
   219     CNcdNodeIdentifier* metaIdentifier =
       
   220                     NcdNodeIdentifierEditor::CreateMetaDataIdentifierLC( *iNodeIdentifier );
       
   221     
       
   222     switch ( iLoadMode )
       
   223         {
       
   224         case EContentSource:
       
   225             {
       
   226             DLTRACE(("Should never come here, ERROR"));
       
   227             DASSERT(0);
       
   228             User::Leave( KErrGeneral );
       
   229             break;
       
   230             }
       
   231         case ESingleNode:
       
   232             {
       
   233             DASSERT( iNodeIdentifier );
       
   234             DLINFO(( _L("iNodeIdentifier: ns= %S, id= %S, aData: ns= %S, id= %S"),
       
   235                 &iNodeIdentifier->NodeNameSpace(), &iNodeIdentifier->NodeId(),
       
   236                 &aData->Namespace(), &aData->Id() ));
       
   237             // Because aData contains metadata ids, we have to get
       
   238             // the metadata id from the iNodeIdentifier
       
   239             
       
   240             if ( aData->Id() == metaIdentifier->NodeId() && 
       
   241                 aData->Namespace() == metaIdentifier->NodeNameSpace() )
       
   242                 {
       
   243                 DLTRACE(("ESingleNode"));
       
   244                 // Because the data id is same as the meta id, we know
       
   245                 // that this can not be the root search. Root search namespace
       
   246                 // and id are defined locally here in the client, not in the 
       
   247                 // web server.
       
   248                 
       
   249                 CNcdNodeManager::TNcdRefHandleMode mode;
       
   250                 if( CNcdNodeFactory::NodePurposeL(
       
   251                     iNodeManager->NodeL( *iNodeIdentifier ) ) ==
       
   252                         CNcdNodeFactory::ENcdSearchNode )
       
   253                     {
       
   254                     mode = CNcdNodeManager::EUpdate;
       
   255                     }
       
   256                 else
       
   257                     {
       
   258                     mode =  CNcdNodeManager::EInsert;
       
   259                     }
       
   260                 
       
   261                 iNodeManager->RefHandlerL( *iParentIdentifier,
       
   262                     *aData,
       
   263                     iClientUid,
       
   264                     mode,
       
   265                     0,
       
   266                     iParentType,
       
   267                     CNcdNodeFactory::ENcdSearchNode,
       
   268                     CNcdNodeFactory::ENcdSearchNode );
       
   269                 nodeAdded = ETrue;
       
   270                 }
       
   271             else if( aData->ParentId() == metaIdentifier->NodeId() &&
       
   272                 aData->ParentNamespace() == metaIdentifier->NodeNameSpace() )
       
   273                 {
       
   274                 DLINFO(("ESingleNode, adding children"));
       
   275                 // A child of the node that we are loading is received
       
   276                 
       
   277                                     
       
   278                 CNcdNode& node = 
       
   279                     iNodeManager->RefHandlerL( *iNodeIdentifier,
       
   280                                                 *aData,
       
   281                                                 iClientUid,
       
   282                                                 CNcdNodeManager::EInsert, // use insertion because child count is not known yet
       
   283                                                 iNodeIndex++,
       
   284                                                 CNcdNodeFactory::ENcdNodeFolder,
       
   285                                                 CNcdNodeFactory::ENcdSearchNode,
       
   286                                                 CNcdNodeFactory::ENcdSearchNode );
       
   287                                                 
       
   288                 // Before saving the node information make sure that the node remote info is
       
   289                 // set correctly. Because nodeAdded will be set true below the node will be 
       
   290                 // saved in the end of this function.
       
   291                 if ( aData->RemoteUri() != KNullDesC )
       
   292                     {
       
   293                     DLINFO((_L("Remote search node: %S"), &node.Identifier().NodeId()));
       
   294                     node.NodeLinkL().SetRemoteFlag( ETrue );
       
   295                     if ( iNodeManager->SearchFolderL( *iNodeIdentifier ).IsTransparent() )
       
   296                         {
       
   297                         DLINFO(("Parent is transparent folder, add child to remote folder array"));
       
   298                         iRemoteFoldersChildOfTransparent.AppendL( CNcdNodeIdentifier::NewLC( node.Identifier() ) );
       
   299                         CleanupStack::Pop(); // the nodeidentifier
       
   300                         }
       
   301                     else if ( iRecursionLeft ) 
       
   302                         {
       
   303                         // Sub operations should not go any further in recursion
       
   304                         DLINFO(("Recursion left"));
       
   305                         iRemoteFolders.AppendL( CNcdNodeIdentifier::NewLC( node.Identifier() ) );
       
   306                         CleanupStack::Pop(); // the nodeidentifier
       
   307                         }
       
   308                      
       
   309                     }
       
   310                 else
       
   311                     {
       
   312                     DLINFO((_L("Normal search node: %S"), &node.Identifier().NodeId()));
       
   313                     node.NodeLinkL().SetRemoteFlag( EFalse );
       
   314                     }
       
   315                            
       
   316                 // The parent is not the node identified by the iParentIdentifier
       
   317                 tmpSearchParentIdentifier = iNodeIdentifier;
       
   318                 nodeAdded = ETrue;
       
   319                 }
       
   320             break;
       
   321             }
       
   322             
       
   323         case EChildren:
       
   324             {
       
   325             DLTRACE(("EChildren"));
       
   326             DASSERT( iNodeIdentifier );
       
   327 
       
   328             // Get the parent node. So, we can use its link to get the metadataidentifier.
       
   329             // The parent always has the link information set here.    
       
   330             CNcdNode& currentNode = iNodeManager->NodeL( *iNodeIdentifier );
       
   331             DLNODEID( currentNode.NodeLinkL().MetaDataIdentifier() );
       
   332             if ( aData->Id() == currentNode.NodeLinkL().MetaDataIdentifier().NodeId() && 
       
   333                 aData->Namespace() == currentNode.NodeLinkL().MetaDataIdentifier().NodeNameSpace() )
       
   334                 {
       
   335                 DLINFO(("EChildren Add parent"));
       
   336                 // Get the actual parent for this operation. This is required to check
       
   337                 // if the parent is root or some other kind of folder.
       
   338                 CNcdNode& addParent = iNodeManager->NodeL( *iParentIdentifier );                    
       
   339                 // add parent
       
   340                 iNodeManager->RefHandlerL( *iParentIdentifier,
       
   341                     *aData,
       
   342                     iClientUid,
       
   343                     CNcdNodeManager::EUpdate,
       
   344                     0, // Should give no index in this case
       
   345                     CNcdNodeFactory::NodeTypeL( addParent ),
       
   346                     CNcdNodeFactory::ENcdSearchNode,
       
   347                     CNcdNodeFactory::ENcdSearchNode );
       
   348                 nodeAdded = ETrue;
       
   349                 // Structure loaded for parent -> send update notification
       
   350                 // for parent node so that it gets internalized.
       
   351                 CNcdNodeIdentifier* loadedNodeId = 
       
   352                     CNcdNodeIdentifier::NewLC( currentNode.Identifier() );
       
   353                 iLoadedNodes.AppendL( loadedNodeId );
       
   354                 CleanupStack::Pop( loadedNodeId );
       
   355                 }
       
   356             else if ( aData->ParentId() == metaIdentifier->NodeId() ||
       
   357                 aData->ParentNamespace() == metaIdentifier->NodeNameSpace() )
       
   358                 {
       
   359                 DLINFO(("EChildren"));
       
   360                 // add child
       
   361                 // We are loading the children of the current node that is
       
   362                 // identified by the iNodeIdentifier.
       
   363                 CNcdNode& node = 
       
   364                     iNodeManager->RefHandlerL( *iNodeIdentifier,
       
   365                                                 *aData,
       
   366                                                 iClientUid,
       
   367                                                 CNcdNodeManager::EReplace,
       
   368                                                 iNodeIndex++,
       
   369                                                 CNcdNodeFactory::ENcdNodeFolder,
       
   370                                                 CNcdNodeFactory::ENcdSearchNode,
       
   371                                                 CNcdNodeFactory::ENcdSearchNode );
       
   372 
       
   373                 // Before saving the node information make sure that the node remote info is
       
   374                 // set correctly. Because nodeAdded will be set true below the node will be 
       
   375                 // saved in the end of this function.
       
   376                 if ( aData->RemoteUri() != KNullDesC )
       
   377                     {
       
   378                     DLINFO((_L("Remote search node: %S"), &node.Identifier().NodeId()));
       
   379                     node.NodeLinkL().SetRemoteFlag( ETrue );
       
   380                     CNcdNodeIdentifier* identifier = CNcdNodeIdentifier::NewLC( node.Identifier() );
       
   381                     iRemoteFolders.AppendL( identifier );
       
   382                     CleanupStack::Pop( identifier );
       
   383                     }
       
   384                 else
       
   385                     {
       
   386                     DLINFO((_L("Normal search node: %S"), &node.Identifier().NodeId()));
       
   387                     node.NodeLinkL().SetRemoteFlag( EFalse );
       
   388                     }
       
   389                             
       
   390                 // The parent is not the node identified by the iParentIdentifier
       
   391                 tmpSearchParentIdentifier = iNodeIdentifier;
       
   392                 nodeAdded = ETrue;
       
   393                 }
       
   394             break;
       
   395             }
       
   396         }
       
   397     CleanupStack::PopAndDestroy( metaIdentifier );
       
   398             
       
   399     // add search filter to folder, this is needed so that consecutive
       
   400     // search ops (started while paging results) can get the filter
       
   401     if ( nodeAdded )
       
   402         {
       
   403         CNcdNodeIdentifier* searchMetaIdentifier = 
       
   404             CNcdNodeIdentifier::NewLC( aData->Namespace(),
       
   405                                        aData->Id(), 
       
   406                                        aData->ServerUri(),
       
   407                                        iClientUid );
       
   408         CNcdSearchNodeFolder& searchFolder = iNodeManager->SearchFolderL(
       
   409             *tmpSearchParentIdentifier,
       
   410             *searchMetaIdentifier );
       
   411         searchFolder.SetSearchFilterL( *iSearchFilter );
       
   412         if( iLoadMode == ESingleNode && CNcdNodeFactory::NodePurposeL(
       
   413             iNodeManager->NodeL( *iNodeIdentifier ) ) !=
       
   414                 CNcdNodeFactory::ENcdSearchNode )
       
   415             {
       
   416             // search op started for a normal node, add origin identifier
       
   417             searchFolder.SetOriginIdentifierL( *iNodeIdentifier );
       
   418             }
       
   419         iNodeManager->DbSaveNodeL( searchFolder );
       
   420         CleanupStack::PopAndDestroy( searchMetaIdentifier );
       
   421         }
       
   422     
       
   423     // Delete data because ownership has been transferred.
       
   424     CleanupStack::PopAndDestroy( aData );
       
   425     
       
   426     DLTRACEOUT((""));
       
   427     }
       
   428     
       
   429 // ---------------------------------------------------------------------------
       
   430 // ?implementation_description
       
   431 // ---------------------------------------------------------------------------
       
   432 //    
       
   433 void CNcdSearchOperation::FolderDataL(
       
   434     MNcdPreminetProtocolDataEntity* aData )
       
   435     {
       
   436     DLTRACEIN((""));
       
   437     if ( aData != NULL )
       
   438         {
       
   439         TInt err( KErrNone );
       
   440         TRAP( err,
       
   441         // Normal PushL causes USER 42
       
   442         CleanupDeletePushL( aData );
       
   443         
       
   444         // This node will contain the metadata that is updated by calling
       
   445         // the handler function.
       
   446         // Notice that after this the metadata has also been created.
       
   447         // So, metadata can be directly used.
       
   448         CNcdNodeIdentifier* parentIdentifier( NULL );
       
   449         TBool addMetaData = ETrue;
       
   450         if( iLoadMode == EChildren || iLoadMode == ESingleNode )
       
   451             {
       
   452             DLINFO(("EChildren"));
       
   453             DASSERT( iNodeIdentifier );
       
   454             CNcdNodeIdentifier* metaIdentifier = 
       
   455                 NcdNodeIdentifierEditor::CreateMetaDataIdentifierL( *iNodeIdentifier );
       
   456             if ( aData->Id() != metaIdentifier->NodeId() || 
       
   457                  aData->Namespace() != metaIdentifier->NodeNameSpace() )
       
   458                 {
       
   459                 // aData must be child of iNodeIdentifier
       
   460                 parentIdentifier = CNcdNodeIdentifier::NewLC( *iNodeIdentifier );
       
   461                 }
       
   462             delete metaIdentifier;
       
   463             metaIdentifier = NULL;
       
   464             }
       
   465         if( addMetaData )
       
   466             {
       
   467             // set iParentIdentifier as parent if not set otherwise, this would be the case of a
       
   468             // normal top-level node from a content source
       
   469             if ( ! parentIdentifier ) 
       
   470                 {
       
   471                 parentIdentifier = CNcdNodeIdentifier::NewLC( *iParentIdentifier );
       
   472                 }
       
   473                 
       
   474             CNcdNode& node = 
       
   475                 iNodeManager->DataHandlerL( *parentIdentifier, *aData, iClientUid );
       
   476                 
       
   477             CleanupStack::PopAndDestroy( parentIdentifier );
       
   478 
       
   479             // Notice that the loaded nodes should contain the actual node identifier
       
   480             // instead of metadata identifier, because the identifiers are returned to
       
   481             // the proxy side after operation completes.
       
   482             CNcdNodeIdentifier* loadedNodeId = 
       
   483                 CNcdNodeIdentifier::NewLC( node.Identifier() );
       
   484             iLoadedNodes.AppendL( loadedNodeId );
       
   485             CleanupStack::Pop( loadedNodeId );
       
   486             
       
   487             DLINFO(("node loaded, id: %S", &node.Identifier().NodeId() ));
       
   488 
       
   489             // If the data contains icon id and datablock id, they are stored until
       
   490             // the datablock arrives later (in DataBlocksL method).
       
   491             const MNcdPreminetProtocolIcon* icon = aData->Icon();
       
   492             if ( icon != NULL ) 
       
   493                 {
       
   494                 const TDesC& iconId = icon->Id();
       
   495                 const TDesC& dataBlockId = icon->DataBlock();
       
   496                 if ( iconId != KNullDesC && dataBlockId != KNullDesC ) 
       
   497                     {
       
   498                     // Icon id may be mapped to the metadata id here
       
   499                     MapIconIdForDataBlockL( iconId, dataBlockId, 
       
   500                                             node.NodeMetaDataL().Identifier() );
       
   501                     // Notice that here we need to get the node by using the
       
   502                     // parent identifier and metadata id, because the metadata
       
   503                     // identifier itself is not enough to identify the node.
       
   504                     node.NodeMetaDataL().IconL().SetIconDataReady( EFalse );
       
   505                     }
       
   506                 }
       
   507             }
       
   508         else if ( parentIdentifier )
       
   509             {
       
   510             CleanupStack::PopAndDestroy( parentIdentifier );
       
   511             }
       
   512 
       
   513         // Delete data because ownership has been transferred.
       
   514         CleanupStack::PopAndDestroy( aData );
       
   515         ); //TRAPD
       
   516         if( err != KErrNone )
       
   517             {
       
   518             iError = err;
       
   519             iLoadNodeState = EFailed;
       
   520             }
       
   521         }
       
   522     RunOperation();
       
   523     
       
   524     DLTRACEOUT((""));
       
   525     }
       
   526     
       
   527     
       
   528 // ---------------------------------------------------------------------------
       
   529 // ?implementation_description
       
   530 // ---------------------------------------------------------------------------
       
   531 //
       
   532 void CNcdSearchOperation::ItemRefL( MNcdPreminetProtocolItemRef* aData )
       
   533     {
       
   534     DLTRACEIN((""));
       
   535 
       
   536     // Item references are handled only when children are loaded or if the 
       
   537     // search mode is not ENormal
       
   538     //
       
   539     // If all item refs were handled recursive searching would be veeery
       
   540     // slow and we might run out of memory due to very high number of 
       
   541     // nodes (800 and more)
       
   542     if ( ( iSearchFilter->SearchMode() == MNcdSearchFilter::ENormal && 
       
   543            iLoadMode != EChildren &&
       
   544            !iNodeManager->SearchFolderL( *iNodeIdentifier ).IsTransparent() ) || 
       
   545          !aData )
       
   546         {
       
   547         delete aData;
       
   548         DLTRACEOUT(("Not loading children or no data"));
       
   549         return;
       
   550         }
       
   551             
       
   552     TRAPD( err, DoItemRefL( aData ) );
       
   553 
       
   554     // Delete data because ownership has been transferred.
       
   555     delete aData;     
       
   556     aData = NULL;    
       
   557  
       
   558     if( err != KErrNone )
       
   559         {
       
   560         DLERROR(("Error: %d", err));
       
   561         iError = err;
       
   562         iLoadNodeState = EFailed;
       
   563         }
       
   564         
       
   565     RunOperation();    
       
   566     }    
       
   567     
       
   568     
       
   569 // ---------------------------------------------------------------------------
       
   570 // 
       
   571 // ---------------------------------------------------------------------------
       
   572 //
       
   573 void CNcdSearchOperation::DoItemRefL( MNcdPreminetProtocolItemRef* aData )
       
   574     {
       
   575     DLTRACEIN((""));
       
   576     // Because aData contains metadata ids, we have to get
       
   577     // the metadata id from the iNodeIdentifier
       
   578     CNcdNodeIdentifier* metaIdentifier =
       
   579         NcdNodeIdentifierEditor::CreateMetaDataIdentifierLC( *iNodeIdentifier );
       
   580     
       
   581     switch ( iLoadMode )
       
   582         {
       
   583         case EContentSource:
       
   584             {                    
       
   585             DLTRACE(("Should never come here, ERROR"));
       
   586             DASSERT(0);
       
   587             break;
       
   588             }
       
   589             
       
   590         case ESingleNode:
       
   591             {
       
   592             DLINFO(("Search single node"));
       
   593             DASSERT( iNodeIdentifier );
       
   594             
       
   595             if ( aData->Id() == metaIdentifier->NodeId() && 
       
   596                 aData->Namespace() == metaIdentifier->NodeNameSpace() )
       
   597                 {
       
   598                 iNodeManager->RefHandlerL( *iParentIdentifier,
       
   599                                             *aData,
       
   600                                             iClientUid,
       
   601                                             CNcdNodeManager::EUpdate,
       
   602                                             0,
       
   603                                             iParentType,
       
   604                                             CNcdNodeFactory::ENcdSearchNode,
       
   605                                             CNcdNodeFactory::ENcdSearchNode );
       
   606                 }
       
   607             else if( aData->ParentId() == metaIdentifier->NodeId() &&
       
   608                 aData->ParentNamespace() == metaIdentifier->NodeNameSpace() )
       
   609                 {
       
   610                 // add child
       
   611                 iNodeManager->RefHandlerL( *iNodeIdentifier,
       
   612                     *aData,
       
   613                     iClientUid,
       
   614                     CNcdNodeManager::EInsert, // use insertion because child count is not known yet
       
   615                     iNodeIndex++,
       
   616                     CNcdNodeFactory::ENcdNodeFolder,
       
   617                     CNcdNodeFactory::ENcdSearchNode,
       
   618                     CNcdNodeFactory::ENcdSearchNode );
       
   619                 }
       
   620             break;
       
   621             }
       
   622             
       
   623         case EChildren:
       
   624             {
       
   625             DLINFO(("Search children"));
       
   626             DASSERT( iNodeIdentifier );
       
   627 
       
   628             // Get the parent node. So, we can use its link to get the metadataidentifier.
       
   629             // The parent always has the link information set here.    
       
   630             CNcdNode& parentNode = iNodeManager->NodeL( *iNodeIdentifier );
       
   631             if ( aData->Id() == parentNode.NodeLinkL().MetaDataIdentifier().NodeId() && 
       
   632                 aData->Namespace() == parentNode.NodeLinkL().MetaDataIdentifier().NodeNameSpace() )
       
   633                 {
       
   634                 // add parent
       
   635                 iNodeManager->RefHandlerL( *iParentIdentifier,
       
   636                     *aData,
       
   637                     iClientUid,
       
   638                     CNcdNodeManager::EUpdate,
       
   639                     0,
       
   640                     iParentType,
       
   641                     CNcdNodeFactory::ENcdSearchNode,
       
   642                     CNcdNodeFactory::ENcdSearchNode );
       
   643                 }
       
   644             else if ( aData->ParentId() == metaIdentifier->NodeId() &&
       
   645                 aData->ParentNamespace() == metaIdentifier->NodeNameSpace() )
       
   646                 {
       
   647                 // add child
       
   648                 iNodeManager->RefHandlerL( *iNodeIdentifier,
       
   649                     *aData,
       
   650                     iClientUid,
       
   651                     CNcdNodeManager::EReplace,
       
   652                     iNodeIndex++,
       
   653                     CNcdNodeFactory::ENcdNodeFolder,
       
   654                     CNcdNodeFactory::ENcdSearchNode,
       
   655                     CNcdNodeFactory::ENcdSearchNode );
       
   656                 }
       
   657             break;
       
   658             }
       
   659         }   
       
   660         
       
   661     CleanupStack::PopAndDestroy( metaIdentifier );
       
   662     DLTRACEOUT((""));
       
   663     }
       
   664     
       
   665 
       
   666 void CNcdSearchOperation::ItemDataL(
       
   667     MNcdPreminetProtocolDataEntity* aData )
       
   668     {
       
   669     DLTRACEIN((""));
       
   670 
       
   671     // Item metadata is handled only when children are loaded or if the 
       
   672     // search mode is not ENormal
       
   673     //
       
   674     // If all item refs were handled recursive searching would be veeery
       
   675     // slow and we might run out of memory due to very high number of 
       
   676     // nodes (800 and more)
       
   677     if ( ( iSearchFilter->SearchMode() == MNcdSearchFilter::ENormal && 
       
   678            iLoadMode != EChildren &&
       
   679            !iNodeManager->SearchFolderL( *iNodeIdentifier ).IsTransparent() ) || 
       
   680          !aData )
       
   681         {
       
   682         delete aData;
       
   683         DLTRACEOUT(("Not loading children or no data"));
       
   684         return;
       
   685         }
       
   686             
       
   687     TRAPD( err, DoItemDataL( aData ) );
       
   688 
       
   689     // Delete data because ownership has been transferred.
       
   690     delete aData;     
       
   691     aData = NULL;    
       
   692  
       
   693     if( err != KErrNone )
       
   694         {
       
   695         DLERROR(("Error: %d", err));
       
   696         iError = err;
       
   697         iLoadNodeState = EFailed;
       
   698         }
       
   699         
       
   700     RunOperation();    
       
   701     }    
       
   702 // ---------------------------------------------------------------------------
       
   703 // ?implementation_description
       
   704 // ---------------------------------------------------------------------------
       
   705 //
       
   706 void CNcdSearchOperation::DoItemDataL(
       
   707     MNcdPreminetProtocolDataEntity* aData )
       
   708     {
       
   709     DLTRACEIN((""));
       
   710     TBool addMetaData = ETrue;
       
   711     CNcdNodeIdentifier* parentIdentifier( NULL );
       
   712     if( iLoadMode == EChildren || iLoadMode == ESingleNode )
       
   713         {
       
   714         DLINFO(("EChildren or ESingleNode"));
       
   715         DASSERT( iNodeIdentifier );
       
   716         CNcdNodeIdentifier* metaIdentifier = 
       
   717             NcdNodeIdentifierEditor::CreateMetaDataIdentifierL( *iNodeIdentifier );
       
   718         if ( aData->Id() != metaIdentifier->NodeId() || 
       
   719              aData->Namespace() != metaIdentifier->NodeNameSpace() )
       
   720             {
       
   721             // aData must be child of iNodeIdentifier
       
   722             parentIdentifier = CNcdNodeIdentifier::NewLC( *iNodeIdentifier );
       
   723             }
       
   724         delete metaIdentifier;
       
   725         metaIdentifier = NULL;
       
   726         }
       
   727     if( addMetaData )
       
   728         {
       
   729         // set iParentIdentifier as parent if not set otherwise, this would be the case of a
       
   730         // normal top-level node from a content source
       
   731         if ( ! parentIdentifier ) 
       
   732             {
       
   733             parentIdentifier = CNcdNodeIdentifier::NewLC( *iParentIdentifier );
       
   734             }
       
   735         
       
   736         // Get the node reference from the data handler.
       
   737         // The node has the given parent and its metadata
       
   738         // will be internalized with the given data.
       
   739         CNcdNode& node =
       
   740             iNodeManager->DataHandlerL( *parentIdentifier, *aData, iClientUid );
       
   741             
       
   742         CleanupStack::PopAndDestroy( parentIdentifier );
       
   743 
       
   744         // Notice that the loaded nodes should contain the actual node identifier
       
   745         // instead of metadata identifier, because the identifiers are returned to
       
   746         // the proxy side after operation completes.
       
   747         CNcdNodeIdentifier* loadedNodeId = 
       
   748             CNcdNodeIdentifier::NewLC( node.Identifier() );
       
   749         iLoadedNodes.AppendL( loadedNodeId );
       
   750         CleanupStack::Pop( loadedNodeId );        
       
   751 
       
   752         // If the data contains icon id and datablock id, they are stored until
       
   753         // the datablock arrives later.
       
   754         const MNcdPreminetProtocolIcon* icon = aData->Icon();
       
   755         if ( icon != NULL ) 
       
   756             {
       
   757             const TDesC& iconId = icon->Id();
       
   758             const TDesC& dataBlockId = icon->DataBlock();
       
   759             if ( iconId != KNullDesC && dataBlockId != KNullDesC ) 
       
   760                 {
       
   761                 // The node metadata was created by using the DataHandlerL
       
   762                 // and inserted for the node.
       
   763                 // So, the metadata can be asked from the node now.
       
   764                 MapIconIdForDataBlockL(iconId, dataBlockId, 
       
   765                                        node.NodeMetaDataL().Identifier() );
       
   766                 node.NodeMetaDataL().IconL().SetIconDataReady( EFalse );
       
   767                 }
       
   768             }
       
   769         }
       
   770     else if ( parentIdentifier )
       
   771         {
       
   772         CleanupStack::PopAndDestroy( parentIdentifier );
       
   773         }
       
   774     DLTRACEOUT((""));
       
   775     }
       
   776     
       
   777 // ---------------------------------------------------------------------------
       
   778 // ?description_if_needed
       
   779 // ---------------------------------------------------------------------------
       
   780 //
       
   781 CNcdSearchOperation::CNcdSearchOperation(
       
   782     TNcdResponseFilterParams aFilterParams,
       
   783     TNcdChildLoadMode aMode,
       
   784     TBool aLoadChildren,
       
   785     CNcdGeneralManager& aGeneralManager,
       
   786     MCatalogsHttpSession& aHttpSession,
       
   787     MNcdOperationRemoveHandler* aRemoveHandler,
       
   788     MNcdOperationQueue* aOperationQueue,
       
   789     MCatalogsSession& aSession,
       
   790     TInt aRecursionLevels,
       
   791     TBool aIsSubOperation )
       
   792     : CNcdLoadNodeOperationImpl( CNcdNodeFactory::ENcdSearchNode, 
       
   793         aFilterParams, aMode, aLoadChildren,
       
   794         aGeneralManager, aHttpSession,
       
   795         aRemoveHandler, aOperationQueue, aSession, aIsSubOperation, ETrue ), 
       
   796       iParentType( CNcdNodeFactory::ENcdNodeFolder ),
       
   797       iRecursionLeft( aRecursionLevels )
       
   798     {
       
   799     iOperationType = ESearchOperation;
       
   800     }
       
   801 
       
   802 // ---------------------------------------------------------------------------
       
   803 // ?description_if_needed
       
   804 // ---------------------------------------------------------------------------
       
   805 //
       
   806 void CNcdSearchOperation::ConstructL(
       
   807     const CNcdNodeIdentifier& aNodeIdentifier,
       
   808     const CNcdNodeIdentifier& aParentIdentifier,
       
   809     const CNcdSearchFilter& aFilter )
       
   810     {
       
   811     DLTRACEIN((""));
       
   812     CNcdLoadNodeOperationImpl::ConstructL( aNodeIdentifier,
       
   813         aParentIdentifier );
       
   814     iSearchFilter = CNcdSearchFilter::NewL( aFilter );
       
   815     DetermineParentTypeL( aNodeIdentifier.ClientUid() );
       
   816     CNcdNode& node = iNodeManager->NodeL( *iNodeIdentifier );
       
   817     if( node.ClassId() == NcdNodeClassIds::ENcdBundleFolderNodeClassId )
       
   818         {
       
   819         // Search op started for a bundle.
       
   820         // Search op started from a non-search node (i.e. starting a new search via search api).
       
   821         // Create a search folder skeleton and replace iNodeIdentifier with the
       
   822         // resulting search folder's identifier. This makes stuff easier elsewhere in the op.
       
   823         CNcdNodeIdentifier* originalIdentifier = iNodeIdentifier;
       
   824         CNcdNode& searchNode = CreateSearchBundleSkeletonL();
       
   825         iNodeIdentifier = CNcdNodeIdentifier::NewL( searchNode.Identifier() );
       
   826         delete originalIdentifier;
       
   827         }
       
   828     else if ( CNcdNodeFactory::NodePurposeL( node.ClassId() ) !=
       
   829         CNcdNodeFactory::ENcdSearchNode )
       
   830         {
       
   831         // Search op started from a non-search node (i.e. starting a new search via search api).
       
   832         // Create a search folder skeleton and replace iNodeIdentifier with the
       
   833         // resulting search folder's identifier. This makes stuff easier elsewhere in the op.
       
   834         CNcdNodeIdentifier* originalIdentifier = iNodeIdentifier;
       
   835         CNcdNode& searchNode = CreateSearchFolderSkeletonL();
       
   836         iNodeIdentifier = CNcdNodeIdentifier::NewL( searchNode.Identifier() );
       
   837         delete originalIdentifier;
       
   838         }
       
   839     DLTRACEOUT((""));
       
   840     }
       
   841 
       
   842 // ---------------------------------------------------------------------------
       
   843 // ?implementation_description
       
   844 // ---------------------------------------------------------------------------
       
   845 //
       
   846 HBufC8* CNcdSearchOperation::CreateRequestLC(
       
   847     CNcdNodeIdentifier* aNodeIdentifier,    
       
   848     TNcdResponseFilterParams aFilterParams,
       
   849     const TDesC& aUri )
       
   850     {
       
   851     //DLTRACEIN(("pagesize=%d, pagestart=%d, depth=%d",aPageSize,aPageStart,aDepth));
       
   852     DLTRACEIN((""));
       
   853     
       
   854     CNcdRequestBrowseSearch* req =
       
   855         NcdRequestGenerator::CreateSearchRequestLC();
       
   856         
       
   857     // create textual representations for content purposes
       
   858     CDesC16ArrayFlat* contentPurposes = new ( ELeave ) CDesC16ArrayFlat(
       
   859         KListGranularity );
       
   860     CleanupStack::PushL( contentPurposes );
       
   861     TUint purposes = iSearchFilter->ContentPurposes();
       
   862     if ( purposes & ENcdItemPurposeMusic )
       
   863         {
       
   864         contentPurposes->AppendL( KNcdContentPurposeMusic );
       
   865         }
       
   866     if ( purposes & ENcdItemPurposeRingtone )
       
   867         {
       
   868         contentPurposes->AppendL( KNcdContentPurposeRingtone );
       
   869         }
       
   870     if ( purposes & ENcdItemPurposeWallpaper )
       
   871         {
       
   872         contentPurposes->AppendL( KNcdContentPurposeWallpaper );
       
   873         }
       
   874     if ( purposes & ENcdItemPurposeVideo )
       
   875         {        
       
   876         contentPurposes->AppendL( KNcdContentPurposeVideo );
       
   877         }
       
   878     if ( purposes & ENcdItemPurposeTheme )
       
   879         {
       
   880         contentPurposes->AppendL( KNcdContentPurposeTheme );
       
   881         }
       
   882     if ( purposes & ENcdItemPurposeApplication )
       
   883         {
       
   884         contentPurposes->AppendL( KNcdContentPurposeApplication );
       
   885         }
       
   886     if ( purposes & ENcdItemPurposeHtmlPage )
       
   887         {        
       
   888         contentPurposes->AppendL( KNcdContentPurposeHtmlPage );
       
   889         }
       
   890     if ( purposes & ENcdItemPurposeGame )
       
   891         {
       
   892         contentPurposes->AppendL( KNcdContentPurposeGame );
       
   893         }
       
   894     if ( purposes & ENcdItemPurposeScreensaver )
       
   895         {
       
   896         contentPurposes->AppendL( KNcdContentPurposeScreensaver );
       
   897         }
       
   898     if ( purposes & ENcdItemPurposeStream )
       
   899         {
       
   900         contentPurposes->AppendL( KNcdContentPurposeStream );
       
   901         }
       
   902         
       
   903     // The parameter is the actual search node identifier. So, it can be used
       
   904     // to get the node from the manager.
       
   905     DLINFO((_L("Search node ns: %S, Id: %S"), 
       
   906             &aNodeIdentifier->NodeNameSpace(), 
       
   907             &aNodeIdentifier->NodeId()));
       
   908     CNcdNode& node = iNodeManager->NodeL( *aNodeIdentifier );
       
   909 
       
   910     req->SetNamespaceL( aNodeIdentifier->NodeNameSpace() );
       
   911     CDesC16ArrayFlat* elements = new (ELeave) CDesC16ArrayFlat(1);
       
   912     CleanupStack::PushL( elements );
       
   913 
       
   914     switch ( iLoadMode )
       
   915         {        
       
   916         case ESingleNode:
       
   917             {
       
   918             DLTRACE(("ESingleNode"))
       
   919             DASSERT( aNodeIdentifier );
       
   920             DASSERT( node.ClassId() != NcdNodeClassIds::ENcdItemNodeClassId );
       
   921             if ( node.ClassId() == NcdNodeClassIds::ENcdSearchItemNodeClassId )
       
   922                 {
       
   923                 // search op started for item, can't do a search
       
   924                 req->SetSearch( EFalse );
       
   925                 }
       
   926             else if ( node.ClassId() == NcdNodeClassIds::ENcdSearchBundleNodeClassId  )
       
   927                 {
       
   928                 DLTRACE(("Searching from bundle, load children as sub-operations"));
       
   929                 CNcdSearchNodeFolder& folder = iNodeManager->SearchFolderL( node.Identifier() );
       
   930                 const RPointerArray<CNcdChildEntity>& children = folder.ChildArray();
       
   931                 for ( TInt i = 0 ; i < children.Count() ; i++ )
       
   932                     {
       
   933                     CNcdNode& childNode = iNodeManager->NodeL( children[i]->Identifier() );
       
   934                     // remote folders are loaded separately
       
   935                     CNcdNodeIdentifier* remoteFolderId =
       
   936                         CNcdNodeIdentifier::NewLC(
       
   937                             childNode.Identifier() );
       
   938                     iRemoteFolders.AppendL( remoteFolderId );
       
   939                     CleanupStack::Pop( remoteFolderId );
       
   940                     }
       
   941                 DLTRACE(("Only search bundle children to load"));
       
   942                 User::Leave( KNcdLoadNodeErrRemoteOnly );
       
   943                 }
       
   944             else
       
   945                 {
       
   946                 // search op started for folder, add search filter
       
   947                 req->AddEntityFilterL( iSearchFilter->Keywords(),
       
   948                     *contentPurposes,
       
   949                     ETrue,
       
   950                     ETrue);
       
   951                 }            
       
   952 
       
   953             req->AddEntityL( 
       
   954                 node.NodeLinkL().MetaDataIdentifier().NodeId(),
       
   955                 node.NodeLinkL().Timestamp(),
       
   956                 ETrue );
       
   957 
       
   958             // Use response filter only for non-transparent folders            
       
   959             if( node.ClassId() == NcdNodeClassIds::ENcdSearchFolderNodeClassId &&
       
   960                 !iNodeManager->SearchFolderL( node.Identifier() ).IsTransparent() )
       
   961                 {
       
   962                 // If not using recursion or we are on the last level of recursion
       
   963                 // we don't need to load the children. This ensures that
       
   964                 // with 0 recursion depth search works just like in 3.1.50
       
   965                 
       
   966                 TInt childCount = INT_MAX; // load all the children
       
   967                 if ( !iRecursionLeft ) 
       
   968                     {
       
   969                     childCount = 1; // load just one child
       
   970                     }
       
   971                     
       
   972                 req->AddResponseFilterL(
       
   973                     childCount, 
       
   974                     0, // pageStart: load from the first child
       
   975                     1, // structureDepth: load child structure
       
   976                     0, // metaDataDepth: don't load child metadata
       
   977                     1, // metaDataPerLevel: only load one metadata per level
       
   978                     *elements,
       
   979                     *elements );
       
   980                 }
       
   981             
       
   982             DLTRACE(("ESingleNode done"))
       
   983             break;
       
   984             }
       
   985             
       
   986         case EChildren:
       
   987             {
       
   988             DLTRACE(("EChildren"));
       
   989             // load children can only be done for folders
       
   990             DASSERT( node.ClassId() == NcdNodeClassIds::ENcdSearchFolderNodeClassId ||
       
   991                 node.ClassId() == NcdNodeClassIds::ENcdFolderNodeClassId ||
       
   992                 node.ClassId() == NcdNodeClassIds::ENcdSearchBundleNodeClassId );
       
   993             
       
   994             // add search filter
       
   995             req->AddEntityFilterL( iSearchFilter->Keywords(),
       
   996                 *contentPurposes,
       
   997                 ETrue,
       
   998                 ETrue);
       
   999 
       
  1000             req->AddEntityL( 
       
  1001                 node.NodeLinkL().MetaDataIdentifier().NodeId(),
       
  1002                 node.NodeLinkL().Timestamp(),
       
  1003                 EFalse ); // Don't load parent metadata.
       
  1004             
       
  1005             // loading children, use filter params
       
  1006             switch ( iChildLoadMode )
       
  1007                 {
       
  1008                 case ELoadStructure:
       
  1009                     {
       
  1010                     DLTRACE(("ELoadStructure"));
       
  1011                     // Calculate correct pagesize.
       
  1012                     TInt pageSize = CalculateStructPageSize(aFilterParams.iPageStart,
       
  1013                         aFilterParams.iPageSize,
       
  1014                         iNodeManager->FolderL( node.Identifier() ),
       
  1015                         iChildLoadMode );
       
  1016                     // Add response filter to get only the desired amount of children.
       
  1017                     req->AddResponseFilterL(
       
  1018                         pageSize,
       
  1019                         aFilterParams.iPageStart,
       
  1020                         1, // structureDepth: load child structure
       
  1021                         0, // metaDataDepth:  don't load child metadata
       
  1022                         0, // metaDataPerLevel: don't load child metadata
       
  1023                         *elements,
       
  1024                         *elements );
       
  1025                     break;
       
  1026                     }
       
  1027                     
       
  1028                 case ELoadMetadata:
       
  1029                     {
       
  1030                     DLTRACE(("ELoadMetadata"));
       
  1031                     // search op should never load metadata for non-search folders
       
  1032                     // as in this case no search is conducted 
       
  1033                     DASSERT( node.ClassId() == 
       
  1034                         NcdNodeClassIds::ENcdSearchFolderNodeClassId ||
       
  1035                         node.ClassId() == NcdNodeClassIds::ENcdSearchBundleNodeClassId);
       
  1036                     CNcdNodeFolder& folder = iNodeManager->FolderL( *aNodeIdentifier );
       
  1037                     // Special handling for bundle folders.
       
  1038                     if ( folder.ClassId() == NcdNodeClassIds::ENcdSearchBundleNodeClassId )
       
  1039                         {
       
  1040                         DLTRACE(("Search bundle -> load children in sub ops."));
       
  1041                         for ( TInt i = aFilterParams.iPageStart ;
       
  1042                              i < aFilterParams.iPageStart + aFilterParams.iPageSize ;
       
  1043                              i++ )
       
  1044                             {
       
  1045                             CNcdNode& childNode = iNodeManager->NodeL( folder.ChildL( i ) );
       
  1046                             
       
  1047                             if ( !childNode.NodeMetaData() || childNode.NodeLinkL().IsExpired() )
       
  1048                                 {
       
  1049                                 // load node only if it has no metadata or if it's expired
       
  1050                             
       
  1051                                 CNcdNodeIdentifier* remoteFolderId =
       
  1052                                     CNcdNodeIdentifier::NewLC( childNode.Identifier() );
       
  1053                                 // Remote folderlist contains actual node ids.
       
  1054                                 iRemoteFolders.AppendL( remoteFolderId );
       
  1055                                 CleanupStack::Pop( remoteFolderId );
       
  1056                                 }
       
  1057                             }
       
  1058                         if( iRemoteFolders.Count() > 0 )
       
  1059                             {
       
  1060                             DLTRACE(("Only remote folders to load"));
       
  1061                             User::Leave( KNcdLoadNodeErrRemoteOnly );
       
  1062                             }
       
  1063                         else
       
  1064                             {
       
  1065                             DLTRACE(("Nothing to do -> complete operation"));
       
  1066                             User::Leave( KNcdLoadNodeErrNothingToDo );
       
  1067                             }
       
  1068                         }
       
  1069                     else
       
  1070                         {
       
  1071                         DLTRACE(("Normal search folder"));
       
  1072                         // Calculate correct pagesize.
       
  1073                         TInt pageSize = CalculateStructPageSize(aFilterParams.iPageStart,
       
  1074                             aFilterParams.iPageSize,
       
  1075                             folder,
       
  1076                             iChildLoadMode );
       
  1077                         // Add response filter to get only the desired amount of children.                      
       
  1078                         req->AddResponseFilterL(
       
  1079                             pageSize, // pageSize: 
       
  1080                             aFilterParams.iPageStart, // pageStart: not applicable in this case as pageSize is 0
       
  1081                             1, // structureDepth: load child structure
       
  1082                             1, // metaDataDepth: load child metadata
       
  1083                             aFilterParams.iPageSize,// metaDataPerLevel: load metadata only for the requested page
       
  1084                             *elements,
       
  1085                             *elements );
       
  1086                         }
       
  1087                     DLTRACE(("ELoadMetadata done"));
       
  1088                     break;
       
  1089                     }
       
  1090                 }
       
  1091             DLTRACE(("EChildren done"));
       
  1092             break;
       
  1093             }
       
  1094             
       
  1095         case EContentSource:
       
  1096         default:
       
  1097             {
       
  1098             // this should never happen
       
  1099             DASSERT( 0 );
       
  1100             break;
       
  1101             }
       
  1102         }
       
  1103     CleanupStack::PopAndDestroy( elements );
       
  1104     CleanupStack::PopAndDestroy( contentPurposes );
       
  1105     
       
  1106     AddQueryResponsesL( req );
       
  1107     
       
  1108     HBufC8* data = NULL;
       
  1109     
       
  1110     data = iProtocol.ProcessPreminetRequestL(
       
  1111         iSession.Context(), *req, aUri );
       
  1112     
       
  1113     CleanupStack::PopAndDestroy( req );
       
  1114     CleanupStack::PushL( data );
       
  1115     return data;
       
  1116     }
       
  1117     
       
  1118 void CNcdSearchOperation::CreateSubOperationsL()
       
  1119     {
       
  1120     DLTRACEIN(("remote folder count: %d", iRemoteFolders.Count()));
       
  1121     
       
  1122     for ( TInt i = 0 ; i < iRemoteFolders.Count() ; i++ )
       
  1123         {
       
  1124         CNcdNode& remoteFolder = iNodeManager->NodeL( *iRemoteFolders[i] );
       
  1125         CNcdSearchOperation* loadOp =
       
  1126             CNcdSearchOperation::NewLC(
       
  1127                 *iRemoteFolders[i],
       
  1128                 remoteFolder.NodeLinkL().ParentIdentifier(),
       
  1129                 *iSearchFilter,
       
  1130                 TNcdResponseFilterParams(),
       
  1131                 iGeneralManager,
       
  1132                 iHttpSession,
       
  1133                 iRemoveHandler,
       
  1134                 iOperationQueue,
       
  1135                 iSession,
       
  1136                 EFalse, // Results in  ESingleNode load mode.
       
  1137                 ELoadStructure, // Not used in ESingleNode mode.
       
  1138                 iRecursionLeft - 1,
       
  1139                 ETrue );
       
  1140         
       
  1141         loadOp->AddObserverL( this );
       
  1142         User::LeaveIfError( loadOp->Start() );
       
  1143         iSubOps.AppendL( loadOp );
       
  1144         CleanupStack::Pop( loadOp );
       
  1145         }
       
  1146         
       
  1147     DLINFO(("Child of transparent count: %d", iRemoteFoldersChildOfTransparent.Count() ));
       
  1148     
       
  1149     // Create load operations for children of transparent folders.
       
  1150     for ( TInt i = 0 ; i < iRemoteFoldersChildOfTransparent.Count() ; i++ )
       
  1151         {
       
  1152         CNcdNode& remoteFolder = iNodeManager->NodeL( *iRemoteFoldersChildOfTransparent[i] );
       
  1153         CNcdSearchOperation* loadOp =
       
  1154             CNcdSearchOperation::NewLC(
       
  1155                 *iRemoteFoldersChildOfTransparent[i],
       
  1156                 remoteFolder.NodeLinkL().ParentIdentifier(),
       
  1157                 *iSearchFilter,
       
  1158                 TNcdResponseFilterParams(),
       
  1159                 iGeneralManager,
       
  1160                 iHttpSession,
       
  1161                 iRemoveHandler,
       
  1162                 iOperationQueue,
       
  1163                 iSession,
       
  1164                 EFalse, // Results in  ESingleNode load mode.
       
  1165                 ELoadStructure, // Not used in ESingleNode mode.
       
  1166                 iRecursionLeft, // Don't decrease the recursion level for child of transparent
       
  1167                 ETrue );
       
  1168         
       
  1169         loadOp->AddObserverL( this );
       
  1170         User::LeaveIfError( loadOp->Start() );
       
  1171         iSubOps.AppendL( loadOp );
       
  1172         CleanupStack::Pop( loadOp );
       
  1173         }
       
  1174     }
       
  1175     
       
  1176 TBool CNcdSearchOperation::IsLoadingNecessaryL()
       
  1177     {
       
  1178     DLTRACEIN((""));
       
  1179     DASSERT( iNodeIdentifier );
       
  1180     CNcdNode& node = iNodeManager->NodeL( *iNodeIdentifier );
       
  1181     
       
  1182     if ( node.ClassId() == NcdNodeClassIds::ENcdSearchRootNodeClassId )
       
  1183         {
       
  1184         DLTRACE(("Search root -> don't load"));
       
  1185         return EFalse;
       
  1186         }
       
  1187     else if ( iLoadMode == EChildren && iChildLoadMode == ELoadMetadata && 
       
  1188               node.ClassId() != NcdNodeClassIds::ENcdSearchBundleNodeClassId )
       
  1189         {
       
  1190         DLTRACE(("ELoadMetadata for normal folder -> load"));
       
  1191         return ETrue;
       
  1192         }
       
  1193     else if( iLoadMode == ESingleNode && node.ClassId() == NcdNodeClassIds::ENcdSearchBundleNodeClassId )
       
  1194         {
       
  1195         DLTRACE(("Search bundle and ESingleNode -> load"));
       
  1196         return ETrue;
       
  1197         }
       
  1198     else if( node.ClassId() == NcdNodeClassIds::ENcdSearchBundleNodeClassId ||
       
  1199         node.ClassId() == NcdNodeClassIds::ENcdBundleFolderNodeClassId )
       
  1200         {
       
  1201         DLTRACE(("Bundle or search bundle -> don't load"));
       
  1202         return EFalse;
       
  1203         }
       
  1204     else
       
  1205         {
       
  1206         DLTRACE(("load"));
       
  1207         return ETrue;
       
  1208         }
       
  1209     }
       
  1210     
       
  1211 TBool CNcdSearchOperation::IsChildClearingNecessaryL()
       
  1212     {
       
  1213     DLTRACEIN((""));
       
  1214     CNcdNode& node = iNodeManager->NodeL( *iNodeIdentifier );
       
  1215     return node.ClassId() == NcdNodeClassIds::ENcdSearchFolderNodeClassId && 
       
  1216            iLoadMode == ESingleNode;
       
  1217     }
       
  1218 
       
  1219 
       
  1220 void CNcdSearchOperation::DetermineParentTypeL( const TUid& aUid )
       
  1221     {
       
  1222     DLTRACEIN((""));
       
  1223     CNcdNodeIdentifier* searchRoot = 
       
  1224         NcdNodeIdentifierEditor::CreateSearchRootIdentifierForClientLC( aUid );
       
  1225     DASSERT( iNodeIdentifier );
       
  1226     DASSERT( iParentIdentifier );
       
  1227     // don't do parent type check for search root as it has no parent
       
  1228     if ( !searchRoot->Equals( *iNodeIdentifier ) ) 
       
  1229         {
       
  1230         iParentType = CNcdNodeFactory::NodeTypeL(
       
  1231         iNodeManager->NodeL( *iParentIdentifier ) );
       
  1232         }
       
  1233     CleanupStack::PopAndDestroy( searchRoot );
       
  1234     }
       
  1235 
       
  1236 CNcdNode& CNcdSearchOperation::CreateSearchBundleSkeletonL()
       
  1237     {
       
  1238     DLTRACEIN((""));
       
  1239     
       
  1240     CNcdNodeFolder& bundle = iNodeManager->FolderL( *iNodeIdentifier );
       
  1241     
       
  1242     CNcdNodeMetaData& bundleMeta = bundle.NodeMetaDataL();
       
  1243     
       
  1244     CNcdSearchNodeBundle& searchBundle = 
       
  1245         iNodeManager->CreateSearchBundleL( bundleMeta.Identifier(),
       
  1246         *iParentIdentifier );
       
  1247         
       
  1248     // Create a link for the bundle
       
  1249     CNcdNodeLink& link = searchBundle.CreateAndSetLinkL();
       
  1250     
       
  1251     // Also, notice that it is essential to insert the metadata identifier into the
       
  1252     // link info. So, the right metadata will be found when the bundle is opened
       
  1253     // from the database. For example when application has been started.
       
  1254     link.SetMetaDataIdentifierL( bundleMeta.Identifier() );
       
  1255     
       
  1256     // Set the metadata to the search bundle because it was not set during creation.
       
  1257     searchBundle.SetNodeMetaDataL( bundleMeta );
       
  1258     
       
  1259     searchBundle.SetSearchFilterL( *iSearchFilter );
       
  1260     
       
  1261     // Set the search bundle as child of the parent node.
       
  1262     iNodeManager->AddToParentL( *iParentIdentifier, bundleMeta.Identifier(), 
       
  1263                                 iParentType,
       
  1264                                 CNcdNodeFactory::ENcdSearchNode,
       
  1265                                 CNcdNodeFactory::ENcdSearchNode,
       
  1266                                 CNcdNodeManager::EInsert, 0 );
       
  1267     
       
  1268     // Add child folders to search bundle
       
  1269     const RPointerArray<CNcdChildEntity>& children = bundle.ChildArray();
       
  1270     for( TInt i = 0 ; i < children.Count() ; i++ )
       
  1271         {
       
  1272         // bundle's children can only be folders
       
  1273         CNcdNodeFolder& bundleChild = iNodeManager->FolderL( children[i]->Identifier() );
       
  1274         
       
  1275         // add only children with search capability
       
  1276         if( iNodeManager->IsCapabilitySupportedL( bundleChild.Identifier(),
       
  1277             NcdCapabilities::KSearch,
       
  1278             iSession.Context() ) )
       
  1279             {
       
  1280             // Bunlde child's metadata may be unavailable so just use the 
       
  1281             // metadata identifier from link
       
  1282             //CNcdNodeMetaData& bundleChildMeta = bundleChild.NodeMetaDataL();
       
  1283             CNcdNodeLink& bundleChildLink = bundleChild.NodeLinkL();
       
  1284             
       
  1285             CNcdSearchNodeFolder& searchBundleChild = 
       
  1286                 iNodeManager->CreateSearchFolderL( bundleChildLink.MetaDataIdentifier(),
       
  1287                 searchBundle.Identifier() );
       
  1288                 
       
  1289             // Create a link for the child
       
  1290             CNcdNodeLink& childLink = searchBundleChild.CreateAndSetLinkL();
       
  1291             
       
  1292             // Also, notice that it is essential to insert the metadata identifier into the
       
  1293             // link info. So, the right metadata will be found when the node is opened
       
  1294             // from the database. For example when application has been started.
       
  1295             childLink.SetMetaDataIdentifierL( bundleChildLink.MetaDataIdentifier() );
       
  1296             
       
  1297             // copy server uri from original node
       
  1298             if( bundleChild.NodeLinkL().RemoteUri() != KNullDesC )
       
  1299                 {
       
  1300                 childLink.SetServerUriL( bundleChild.NodeLinkL().RemoteUri() );
       
  1301                 }
       
  1302             else
       
  1303                 {
       
  1304                 childLink.SetServerUriL( bundleChild.NodeLinkL().ServerUri() );
       
  1305                 }
       
  1306             
       
  1307             // Set the metadata to the bundle folder because it was not set during creation.
       
  1308             //searchBundleChild.SetNodeMetaDataL( bundleChildMeta );
       
  1309             
       
  1310             searchBundleChild.SetSearchFilterL( *iSearchFilter );
       
  1311 
       
  1312             TBool transparent = 
       
  1313                 ( bundleChild.ClassId() == NcdNodeClassIds::ENcdTransparentFolderNodeClassId );
       
  1314                         
       
  1315             searchBundleChild.SetTransparent( transparent );
       
  1316                 
       
  1317             
       
  1318             // Set the folder as child of search bundle.
       
  1319             iNodeManager->AddToParentL( searchBundle.Identifier(), bundleChildLink.MetaDataIdentifier(), 
       
  1320                                         CNcdNodeFactory::ENcdNodeSearchBundle,
       
  1321                                         CNcdNodeFactory::ENcdSearchNode,
       
  1322                                         CNcdNodeFactory::ENcdSearchNode, //This parameter is unused
       
  1323                                         CNcdNodeManager::EAppend, 
       
  1324                                         0,
       
  1325                                         transparent );
       
  1326                                         
       
  1327             searchBundleChild.SetOriginIdentifierL( bundleChild.Identifier() );
       
  1328             iNodeManager->DbSaveNodeL( searchBundleChild );
       
  1329             }
       
  1330         }
       
  1331     iNodeManager->DbSaveNodeL( searchBundle );
       
  1332     return searchBundle;
       
  1333     }
       
  1334 
       
  1335 CNcdNode& CNcdSearchOperation::CreateSearchFolderSkeletonL()
       
  1336     {
       
  1337     DLTRACEIN((""));
       
  1338     
       
  1339     CNcdNodeFolder& folder = iNodeManager->FolderL( *iNodeIdentifier );
       
  1340     
       
  1341     CNcdNodeMetaData& folderMeta = folder.NodeMetaDataL();
       
  1342     
       
  1343     CNcdSearchNodeFolder& searchFolder = 
       
  1344         iNodeManager->CreateSearchFolderL( folderMeta.Identifier(),
       
  1345         *iParentIdentifier );
       
  1346         
       
  1347     // Create a link for the folder
       
  1348     CNcdNodeLink& link = searchFolder.CreateAndSetLinkL();
       
  1349     
       
  1350     // Also, notice that it is essential to insert the metadata identifier into the
       
  1351     // link info. So, the right metadata will be found when the folder is opened
       
  1352     // from the database. For example when application has been started.
       
  1353     link.SetMetaDataIdentifierL( folderMeta.Identifier() );
       
  1354     
       
  1355     // copy server uri from original node
       
  1356     if( folder.NodeLinkL().RemoteUri() != KNullDesC )
       
  1357         {
       
  1358         link.SetServerUriL( folder.NodeLinkL().RemoteUri() );
       
  1359         }
       
  1360     else
       
  1361         {
       
  1362         link.SetServerUriL( folder.NodeLinkL().ServerUri() );
       
  1363         }
       
  1364     
       
  1365     // Set the metadata to the search bundle because it was not set during creation.
       
  1366     searchFolder.SetNodeMetaDataL( folderMeta );
       
  1367     
       
  1368     searchFolder.SetSearchFilterL( *iSearchFilter );
       
  1369     
       
  1370     TBool transparent = 
       
  1371         ( folder.ClassId() == NcdNodeClassIds::ENcdTransparentFolderNodeClassId );
       
  1372         
       
  1373     // Set the search folder as child of the parent node.
       
  1374     iNodeManager->AddToParentL( *iParentIdentifier, 
       
  1375                                 folderMeta.Identifier(), 
       
  1376                                 iParentType,
       
  1377                                 CNcdNodeFactory::ENcdSearchNode,
       
  1378                                 CNcdNodeFactory::ENcdSearchNode,
       
  1379                                 CNcdNodeManager::EInsert, 
       
  1380                                 0,
       
  1381                                 transparent );
       
  1382     
       
  1383     searchFolder.SetOriginIdentifierL( *iNodeIdentifier );
       
  1384     
       
  1385     // Because AddToParentL only saves the parent information after child is added to it
       
  1386     // we should always save the bundle node here. So, it will be usable after client is
       
  1387     // restarted.
       
  1388     iNodeManager->DbSaveNodeL( searchFolder );
       
  1389     
       
  1390     return searchFolder;
       
  1391     }
       
  1392     
       
  1393 void CNcdSearchOperation::ErrorL( MNcdPreminetProtocolError* aData )
       
  1394     {
       
  1395     DLTRACEIN((""));
       
  1396     switch ( aData->Code() )
       
  1397         {
       
  1398         case 404:
       
  1399             {
       
  1400             // Removed/missing nodes need no special handling in search op,
       
  1401             // so just fail the operation.
       
  1402             iError = KNcdErrorNodeWasRemoved;
       
  1403             iLoadNodeState = EFailed;
       
  1404             Cancel();
       
  1405             delete aData;
       
  1406             RunOperation();
       
  1407             break;
       
  1408             }
       
  1409         default:
       
  1410             {
       
  1411             CNcdLoadNodeOperationImpl::ErrorL( aData );
       
  1412             break;
       
  1413             }
       
  1414         }    
       
  1415     }
       
  1416 
       
  1417 TInt CNcdSearchOperation::RemoteFolderCount() const
       
  1418     {
       
  1419     DLTRACEIN((""));
       
  1420     return iRemoteFolders.Count() + iRemoteFoldersChildOfTransparent.Count();
       
  1421     }
       
  1422     
       
  1423     
       
  1424 void CNcdSearchOperation::RemoveChildrenL( CNcdNodeFolder& aFolder ) 
       
  1425     {
       
  1426     DLTRACEIN((""));
       
  1427     aFolder.RemoveChildren();
       
  1428     }
       
  1429