browserutilities/feedsengine/FeedsServer/Server/src/ImportFeedsTask.cpp
changeset 0 dd21522fd290
child 25 0ed94ceaa377
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2005 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 the License "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:  A task to import Feeds.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <S32Mem.h>
       
    20 
       
    21 #include "ImportFeedsTask.h"
       
    22 #include "FeedsDatabase.h"
       
    23 #include "FeedsServer.h"
       
    24 #include "FeedsServerMsg.h"
       
    25 
       
    26 // Root folder related.
       
    27 const TInt  KRootFolderId = 0;
       
    28 
       
    29 // -----------------------------------------------------------------------------
       
    30 // CImportFeedsTask::NewL
       
    31 //
       
    32 // Two-phased constructor.
       
    33 // -----------------------------------------------------------------------------
       
    34 //
       
    35 CImportFeedsTask* CImportFeedsTask::NewL(CFeedsServer& aFeedsServer, 
       
    36         					MImportFeedsTaskObserver& aObserver, const RMessage2& aMessage)
       
    37     {
       
    38     CImportFeedsTask* self = new (ELeave) CImportFeedsTask(aFeedsServer, aObserver, aMessage);
       
    39 
       
    40     CleanupStack::PushL(self);
       
    41     self->ConstructL();
       
    42     CleanupStack::Pop();
       
    43 
       
    44     return self;
       
    45     }
       
    46     
       
    47 // -----------------------------------------------------------------------------
       
    48 // CImportFeedsTask::CImportFeedsTask
       
    49 // C++ default constructor can NOT contain any code, that
       
    50 // might leave.
       
    51 // -----------------------------------------------------------------------------
       
    52 //
       
    53 CImportFeedsTask::CImportFeedsTask(CFeedsServer& aFeedsServer, MImportFeedsTaskObserver& aObserver, const RMessage2& aMessage):
       
    54         CTask(aFeedsServer), iObserver(aObserver), iMessage(aMessage)
       
    55     {
       
    56     	
       
    57     }
       
    58         
       
    59 
       
    60 // -----------------------------------------------------------------------------
       
    61 // CImportFeedsTask::ConstructL
       
    62 // Symbian 2nd phase constructor can leave.
       
    63 // -----------------------------------------------------------------------------
       
    64 //
       
    65 void CImportFeedsTask::ConstructL()
       
    66     {
       
    67     BaseConstructL(ETrue);
       
    68 
       
    69     iIdle = CIdle::NewL(CActive::EPriorityStandard);
       
    70   	iPackedFolder = NULL;
       
    71   	iMoreToAdd = ETrue;
       
    72   	iFeedsDatabase = &(iFeedsServer.Database());
       
    73     }        
       
    74 
       
    75 // -----------------------------------------------------------------------------
       
    76 // CImportFeedsTask::CImportFeedsTask
       
    77 // Deconstructor.
       
    78 // -----------------------------------------------------------------------------
       
    79 //
       
    80 CImportFeedsTask::~CImportFeedsTask()
       
    81     {
       
    82     TRAP_IGNORE( CleanupImportTaskL() );
       
    83 
       
    84 	iImportFile.Close();
       
    85 	iRFs.Close();
       
    86 	
       
    87 	delete iFullImportFileName;
       
    88     delete iPackedFolder;
       
    89     delete iIdle;
       
    90     }
       
    91 
       
    92 // -----------------------------------------------------------------------------
       
    93 // CImportFeedsTask::StartTaskL.
       
    94 //
       
    95 // Starts the task.
       
    96 // -----------------------------------------------------------------------------
       
    97 //
       
    98 void CImportFeedsTask::StartTaskL()
       
    99     {
       
   100 	iImportState = EImportOpenOPMLFile;
       
   101 	iDBTransactInited = EFalse;
       
   102 	iFoundRootFolder = EFalse;
       
   103 
       
   104 	iParentStack.AppendL(KRootFolderId);    
       
   105 	iSiblingIndexStack.AppendL(0);
       
   106 	
       
   107 	iIdle->Start(TCallBack(StartImportStateMachine, this));
       
   108 	}
       
   109 	
       
   110 
       
   111 // -----------------------------------------------------------------------------
       
   112 // CImportFeedsTask::StartImportStateMachine.
       
   113 //
       
   114 // Starts the OPML import task
       
   115 // -----------------------------------------------------------------------------
       
   116 //
       
   117 TBool CImportFeedsTask::StartImportStateMachine(TAny *aPtr)
       
   118 	{
       
   119 	TInt err(KErrNone);
       
   120 	
       
   121     CImportFeedsTask *self = static_cast<CImportFeedsTask *>(aPtr);
       
   122 	
       
   123 	switch(self->iImportState)
       
   124 		{
       
   125 		case EImportOpenOPMLFile :
       
   126 			TRAP(err, self->OpenOPMLFileL());
       
   127 			if(err != KErrNone)
       
   128 				{
       
   129 				self->iObserver.ImportCompleted(err);
       
   130 				return EFalse;
       
   131 				}
       
   132 			self->iImportState = EImportPreparePackedFolder;
       
   133 			return ETrue;
       
   134 			
       
   135 		case EImportPreparePackedFolder:
       
   136 			TRAP(err, self->PreparePackedFolderL());
       
   137 			if(err != KErrNone)
       
   138 				{
       
   139 				self->iObserver.ImportCompleted(err);
       
   140 				return EFalse;
       
   141 				}
       
   142 			self->iImportState = EImportIntoDB;
       
   143 			return ETrue;
       
   144 
       
   145 		case EImportIntoDB:
       
   146 			
       
   147 			TRAP(err, self->ImportIntoDBL());
       
   148 			if(err != KErrNone)
       
   149 				{
       
   150 				self->iObserver.ImportCompleted(err);
       
   151 				return EFalse;
       
   152 				}
       
   153 			if(self->iMoreToAdd)
       
   154 				{
       
   155 				return ETrue;
       
   156 				}
       
   157 			self->iImportState = EImportDone;
       
   158 			self->iObserver.ImportCompleted(KErrNone);
       
   159 			return EFalse;
       
   160 		}
       
   161 	return EFalse;
       
   162 	}
       
   163 	
       
   164 // -----------------------------------------------------------------------------
       
   165 // CImportFeedsTask::CleanupImportTask.
       
   166 //
       
   167 // Cancel the ongoing OPML import task
       
   168 // -----------------------------------------------------------------------------
       
   169 //
       
   170 void CImportFeedsTask::CleanupImportTaskL()
       
   171 	{
       
   172 	if(iImportState ==  EImportIntoDB && iMoreToAdd)
       
   173 		{
       
   174 		iFeedsDatabase->CommitImportTransaction();
       
   175 		
       
   176 		// Rollback didnt work with tables having index, so deleting all the added records :(
       
   177 		iFeedsDatabase->DeleteFeedTableRecordsL(iFeedIds);
       
   178 		iFeedsDatabase->DeleteFolderListTableRecordsL(iFolderItemIds);
       
   179 		
       
   180 		if(iDBTransactInited)
       
   181 			ReleaseImportTables();
       
   182 		}
       
   183 	}
       
   184 
       
   185 // -----------------------------------------------------------------------------
       
   186 // CImportFeedsTask::ExtractClientImportMessageL.
       
   187 //
       
   188 // Extract the client passes message
       
   189 // -----------------------------------------------------------------------------
       
   190 //
       
   191 void CImportFeedsTask::OpenOPMLFileL()
       
   192 	{
       
   193     User::LeaveIfError(iRFs.Connect());
       
   194 	User::LeaveIfError(iImportFile.Open(iRFs, *iFullImportFileName, EFileRead | EFileShareReadersOnly));
       
   195 	}
       
   196 
       
   197 // -----------------------------------------------------------------------------
       
   198 // CImportFeedsTask::PreparePackedFolderL.
       
   199 //
       
   200 // Creates the packed folder by parsing the OPML file
       
   201 // -----------------------------------------------------------------------------
       
   202 //
       
   203 void CImportFeedsTask::PreparePackedFolderL()
       
   204 	{
       
   205 	iPackedFolder = iFeedsServer.ImportFolderL(iImportFile, iDispImportFileName);	
       
   206 	}
       
   207 
       
   208 // -----------------------------------------------------------------------------
       
   209 // CImportFeedsTask::ReleaseImportTablesCallback.
       
   210 //
       
   211 // Callback function for import task completion
       
   212 // -----------------------------------------------------------------------------
       
   213 //
       
   214 void CImportFeedsTask::ReleaseImportTablesCallback(TAny *ptr)
       
   215 	{
       
   216 	CImportFeedsTask *self = static_cast<CImportFeedsTask *>(ptr);
       
   217 	self->iFeedsDatabase->CommitImportTransaction();
       
   218 
       
   219 	self->ReleaseImportTables();
       
   220 	}
       
   221 
       
   222 // -----------------------------------------------------------------------------
       
   223 // CImportFeedsTask::ReleaseImportTables.
       
   224 //
       
   225 // Closes all the OPML import related tables
       
   226 // -----------------------------------------------------------------------------
       
   227 //
       
   228 void CImportFeedsTask::ReleaseImportTables()
       
   229 	{
       
   230 	iFeedsDatabase->ReleaseImportTables();
       
   231 	}
       
   232 
       
   233 // -----------------------------------------------------------------------------
       
   234 // CImportFeedsTask::ImportIntoDBL.
       
   235 //
       
   236 // Starts importing the packed folder into DB
       
   237 // -----------------------------------------------------------------------------
       
   238 //
       
   239 void CImportFeedsTask::ImportIntoDBL()
       
   240 	{
       
   241 
       
   242 	CleanupStack::PushL(TCleanupItem(&ReleaseImportTablesCallback, this));
       
   243 
       
   244 	if(!iDBTransactInited)
       
   245 		{
       
   246 		iFeedsDatabase->PrepareImportTransationsL(); // Open tables, mark start of transactions
       
   247   		iDBTransactInited = ETrue;
       
   248 		}
       
   249 
       
   250 	ImportFoldersL(); // Import record by record
       
   251 
       
   252 	if(!iMoreToAdd)
       
   253 		{
       
   254     	CleanupStack::PopAndDestroy(/*ReleaseImportTablesCallback*/);
       
   255 		}
       
   256 	else
       
   257 		CleanupStack::Pop(/*ReleaseImportTablesCallback*/);
       
   258 	}
       
   259 
       
   260 // -----------------------------------------------------------------------------
       
   261 // CImportFeedsTask::ImportFoldersL.
       
   262 //
       
   263 // Imports the packed folder into DB
       
   264 // -----------------------------------------------------------------------------
       
   265 //
       
   266 void CImportFeedsTask::ImportFoldersL()
       
   267     {
       
   268     TInt                parent;
       
   269     TInt                siblingIndex;
       
   270     TInt                folderId;
       
   271     TPtrC               title;
       
   272     TPtrC               url;
       
   273     TInt                entryId;
       
   274     TInt                feedId;
       
   275     TInt                newfeedId;
       
   276     TTime               timestamp;
       
   277     TInt                unreadCount;
       
   278     TInt 				statusCode;
       
   279     TInt 				freq;
       
   280 	if(!iPackedFolder->HasNextToken()) 
       
   281 		{
       
   282 		iMoreToAdd = EFalse;
       
   283 		return;
       
   284 		}
       
   285 	
       
   286 	iMoreToAdd = ETrue;
       
   287 		
       
   288 	TUint token = iPackedFolder->NextToken();
       
   289         
       
   290 	switch (token)
       
   291 		{
       
   292 		case EFolderTokenFolderBegin:
       
   293                 // Extract the attributes.
       
   294 			iPackedFolder->ExtractAttributes(title, url, entryId, feedId, timestamp, unreadCount, statusCode, freq);
       
   295                 
       
   296             // The first folder in the PackedFolder is the root-folder.  There is no
       
   297             // reason to store this folder in the database, as such this folder is skipped.
       
   298             if (!iFoundRootFolder)
       
   299                 {
       
   300                 iFoundRootFolder = ETrue;
       
   301                 return;
       
   302                 }
       
   303 
       
   304             // Determine the parent and its sibling index.
       
   305             parent = iParentStack[iParentStack.Count() - 1];
       
   306             siblingIndex = iSiblingIndexStack[iSiblingIndexStack.Count() - 1];
       
   307             iSiblingIndexStack[iSiblingIndexStack.Count() - 1]++;
       
   308 
       
   309             //create a sibling index hole
       
   310             iFeedsDatabase->CreateSiblingIndexHoleL(parent, siblingIndex, 1);
       
   311 
       
   312             // Add the folder.      
       
   313             iFeedsDatabase->FolderItemAddHelperL(iFolderListId, title, KNullDesC, 
       
   314                     ETrue, siblingIndex, parent, folderId, newfeedId, freq);
       
   315 
       
   316             // Push this folder on the stack as the active parent.
       
   317             iParentStack.AppendL(folderId);
       
   318             iSiblingIndexStack.AppendL(0);
       
   319             
       
   320             iFolderItemIds.AppendL(folderId);
       
   321             break;
       
   322 
       
   323         case EFolderTokenFolderEnd:
       
   324             // Pop this folder off of the stacks.
       
   325             iParentStack.Remove(iParentStack.Count() - 1);
       
   326             iSiblingIndexStack.Remove(iSiblingIndexStack.Count() - 1);
       
   327             break;
       
   328 
       
   329         case EFolderTokenFeed:
       
   330             // Extract the attributes.
       
   331             iPackedFolder->ExtractAttributes(title, url, entryId, feedId, timestamp, unreadCount, statusCode, freq);
       
   332 
       
   333             // Determine the parent and its sibling index.
       
   334             parent = iParentStack[iParentStack.Count() - 1];
       
   335             siblingIndex = iSiblingIndexStack[iSiblingIndexStack.Count() - 1];
       
   336             
       
   337             // Add the feed.                
       
   338             TRAPD( err, iFeedsDatabase->FolderItemAddHelperL(iFolderListId, title, url, 
       
   339                     EFalse, siblingIndex, parent, folderId, newfeedId, freq) );
       
   340 
       
   341             // Ignore problematic ones and continue to the next token
       
   342             if( err == KErrNone && newfeedId >= 0)
       
   343                 {
       
   344                 iSiblingIndexStack[iSiblingIndexStack.Count() - 1]++;
       
   345                 
       
   346                 iFolderItemIds.AppendL(folderId);
       
   347                 iFeedIds.AppendL(newfeedId);
       
   348                 }
       
   349             break;               
       
   350         }
       
   351     }
       
   352