browserutilities/feedsengine/FeedsServer/Server/src/ImportFeedsTask.cpp
changeset 0 dd21522fd290
child 36 0ed94ceaa377
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/browserutilities/feedsengine/FeedsServer/Server/src/ImportFeedsTask.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,352 @@
+/*
+* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  A task to import Feeds.
+*
+*/
+
+
+#include <S32Mem.h>
+
+#include "ImportFeedsTask.h"
+#include "FeedsDatabase.h"
+#include "FeedsServer.h"
+#include "FeedsServerMsg.h"
+
+// Root folder related.
+const TInt  KRootFolderId = 0;
+
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::NewL
+//
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CImportFeedsTask* CImportFeedsTask::NewL(CFeedsServer& aFeedsServer, 
+        					MImportFeedsTaskObserver& aObserver, const RMessage2& aMessage)
+    {
+    CImportFeedsTask* self = new (ELeave) CImportFeedsTask(aFeedsServer, aObserver, aMessage);
+
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+
+    return self;
+    }
+    
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::CImportFeedsTask
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CImportFeedsTask::CImportFeedsTask(CFeedsServer& aFeedsServer, MImportFeedsTaskObserver& aObserver, const RMessage2& aMessage):
+        CTask(aFeedsServer), iObserver(aObserver), iMessage(aMessage)
+    {
+    	
+    }
+        
+
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CImportFeedsTask::ConstructL()
+    {
+    BaseConstructL(ETrue);
+
+    iIdle = CIdle::NewL(CActive::EPriorityStandard);
+  	iPackedFolder = NULL;
+  	iMoreToAdd = ETrue;
+  	iFeedsDatabase = &(iFeedsServer.Database());
+    }        
+
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::CImportFeedsTask
+// Deconstructor.
+// -----------------------------------------------------------------------------
+//
+CImportFeedsTask::~CImportFeedsTask()
+    {
+    TRAP_IGNORE( CleanupImportTaskL() );
+
+	iImportFile.Close();
+	iRFs.Close();
+	
+	delete iFullImportFileName;
+    delete iPackedFolder;
+    delete iIdle;
+    }
+
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::StartTaskL.
+//
+// Starts the task.
+// -----------------------------------------------------------------------------
+//
+void CImportFeedsTask::StartTaskL()
+    {
+	iImportState = EImportOpenOPMLFile;
+	iDBTransactInited = EFalse;
+	iFoundRootFolder = EFalse;
+
+	iParentStack.AppendL(KRootFolderId);    
+	iSiblingIndexStack.AppendL(0);
+	
+	iIdle->Start(TCallBack(StartImportStateMachine, this));
+	}
+	
+
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::StartImportStateMachine.
+//
+// Starts the OPML import task
+// -----------------------------------------------------------------------------
+//
+TBool CImportFeedsTask::StartImportStateMachine(TAny *aPtr)
+	{
+	TInt err(KErrNone);
+	
+    CImportFeedsTask *self = static_cast<CImportFeedsTask *>(aPtr);
+	
+	switch(self->iImportState)
+		{
+		case EImportOpenOPMLFile :
+			TRAP(err, self->OpenOPMLFileL());
+			if(err != KErrNone)
+				{
+				self->iObserver.ImportCompleted(err);
+				return EFalse;
+				}
+			self->iImportState = EImportPreparePackedFolder;
+			return ETrue;
+			
+		case EImportPreparePackedFolder:
+			TRAP(err, self->PreparePackedFolderL());
+			if(err != KErrNone)
+				{
+				self->iObserver.ImportCompleted(err);
+				return EFalse;
+				}
+			self->iImportState = EImportIntoDB;
+			return ETrue;
+
+		case EImportIntoDB:
+			
+			TRAP(err, self->ImportIntoDBL());
+			if(err != KErrNone)
+				{
+				self->iObserver.ImportCompleted(err);
+				return EFalse;
+				}
+			if(self->iMoreToAdd)
+				{
+				return ETrue;
+				}
+			self->iImportState = EImportDone;
+			self->iObserver.ImportCompleted(KErrNone);
+			return EFalse;
+		}
+	return EFalse;
+	}
+	
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::CleanupImportTask.
+//
+// Cancel the ongoing OPML import task
+// -----------------------------------------------------------------------------
+//
+void CImportFeedsTask::CleanupImportTaskL()
+	{
+	if(iImportState ==  EImportIntoDB && iMoreToAdd)
+		{
+		iFeedsDatabase->CommitImportTransaction();
+		
+		// Rollback didnt work with tables having index, so deleting all the added records :(
+		iFeedsDatabase->DeleteFeedTableRecordsL(iFeedIds);
+		iFeedsDatabase->DeleteFolderListTableRecordsL(iFolderItemIds);
+		
+		if(iDBTransactInited)
+			ReleaseImportTables();
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::ExtractClientImportMessageL.
+//
+// Extract the client passes message
+// -----------------------------------------------------------------------------
+//
+void CImportFeedsTask::OpenOPMLFileL()
+	{
+    User::LeaveIfError(iRFs.Connect());
+	User::LeaveIfError(iImportFile.Open(iRFs, *iFullImportFileName, EFileRead | EFileShareReadersOnly));
+	}
+
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::PreparePackedFolderL.
+//
+// Creates the packed folder by parsing the OPML file
+// -----------------------------------------------------------------------------
+//
+void CImportFeedsTask::PreparePackedFolderL()
+	{
+	iPackedFolder = iFeedsServer.ImportFolderL(iImportFile, iDispImportFileName);	
+	}
+
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::ReleaseImportTablesCallback.
+//
+// Callback function for import task completion
+// -----------------------------------------------------------------------------
+//
+void CImportFeedsTask::ReleaseImportTablesCallback(TAny *ptr)
+	{
+	CImportFeedsTask *self = static_cast<CImportFeedsTask *>(ptr);
+	self->iFeedsDatabase->CommitImportTransaction();
+
+	self->ReleaseImportTables();
+	}
+
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::ReleaseImportTables.
+//
+// Closes all the OPML import related tables
+// -----------------------------------------------------------------------------
+//
+void CImportFeedsTask::ReleaseImportTables()
+	{
+	iFeedsDatabase->ReleaseImportTables();
+	}
+
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::ImportIntoDBL.
+//
+// Starts importing the packed folder into DB
+// -----------------------------------------------------------------------------
+//
+void CImportFeedsTask::ImportIntoDBL()
+	{
+
+	CleanupStack::PushL(TCleanupItem(&ReleaseImportTablesCallback, this));
+
+	if(!iDBTransactInited)
+		{
+		iFeedsDatabase->PrepareImportTransationsL(); // Open tables, mark start of transactions
+  		iDBTransactInited = ETrue;
+		}
+
+	ImportFoldersL(); // Import record by record
+
+	if(!iMoreToAdd)
+		{
+    	CleanupStack::PopAndDestroy(/*ReleaseImportTablesCallback*/);
+		}
+	else
+		CleanupStack::Pop(/*ReleaseImportTablesCallback*/);
+	}
+
+// -----------------------------------------------------------------------------
+// CImportFeedsTask::ImportFoldersL.
+//
+// Imports the packed folder into DB
+// -----------------------------------------------------------------------------
+//
+void CImportFeedsTask::ImportFoldersL()
+    {
+    TInt                parent;
+    TInt                siblingIndex;
+    TInt                folderId;
+    TPtrC               title;
+    TPtrC               url;
+    TInt                entryId;
+    TInt                feedId;
+    TInt                newfeedId;
+    TTime               timestamp;
+    TInt                unreadCount;
+    TInt 				statusCode;
+    TInt 				freq;
+	if(!iPackedFolder->HasNextToken()) 
+		{
+		iMoreToAdd = EFalse;
+		return;
+		}
+	
+	iMoreToAdd = ETrue;
+		
+	TUint token = iPackedFolder->NextToken();
+        
+	switch (token)
+		{
+		case EFolderTokenFolderBegin:
+                // Extract the attributes.
+			iPackedFolder->ExtractAttributes(title, url, entryId, feedId, timestamp, unreadCount, statusCode, freq);
+                
+            // The first folder in the PackedFolder is the root-folder.  There is no
+            // reason to store this folder in the database, as such this folder is skipped.
+            if (!iFoundRootFolder)
+                {
+                iFoundRootFolder = ETrue;
+                return;
+                }
+
+            // Determine the parent and its sibling index.
+            parent = iParentStack[iParentStack.Count() - 1];
+            siblingIndex = iSiblingIndexStack[iSiblingIndexStack.Count() - 1];
+            iSiblingIndexStack[iSiblingIndexStack.Count() - 1]++;
+
+            //create a sibling index hole
+            iFeedsDatabase->CreateSiblingIndexHoleL(parent, siblingIndex, 1);
+
+            // Add the folder.      
+            iFeedsDatabase->FolderItemAddHelperL(iFolderListId, title, KNullDesC, 
+                    ETrue, siblingIndex, parent, folderId, newfeedId, freq);
+
+            // Push this folder on the stack as the active parent.
+            iParentStack.AppendL(folderId);
+            iSiblingIndexStack.AppendL(0);
+            
+            iFolderItemIds.AppendL(folderId);
+            break;
+
+        case EFolderTokenFolderEnd:
+            // Pop this folder off of the stacks.
+            iParentStack.Remove(iParentStack.Count() - 1);
+            iSiblingIndexStack.Remove(iSiblingIndexStack.Count() - 1);
+            break;
+
+        case EFolderTokenFeed:
+            // Extract the attributes.
+            iPackedFolder->ExtractAttributes(title, url, entryId, feedId, timestamp, unreadCount, statusCode, freq);
+
+            // Determine the parent and its sibling index.
+            parent = iParentStack[iParentStack.Count() - 1];
+            siblingIndex = iSiblingIndexStack[iSiblingIndexStack.Count() - 1];
+            
+            // Add the feed.                
+            TRAPD( err, iFeedsDatabase->FolderItemAddHelperL(iFolderListId, title, url, 
+                    EFalse, siblingIndex, parent, folderId, newfeedId, freq) );
+
+            // Ignore problematic ones and continue to the next token
+            if( err == KErrNone && newfeedId >= 0)
+                {
+                iSiblingIndexStack[iSiblingIndexStack.Count() - 1]++;
+                
+                iFolderItemIds.AppendL(folderId);
+                iFeedIds.AppendL(newfeedId);
+                }
+            break;               
+        }
+    }
+