emailservices/emailstore/message_store/server/src/MsgStoreSortResultRowSet.cpp
changeset 0 8466d47a6819
child 51 d845db10c0d4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/emailstore/message_store/server/src/MsgStoreSortResultRowSet.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,596 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Message store sort result row set implementation.
+*
+*/
+
+
+#include "MsgStoreSortResultRowSet.h"
+#include "ContainerStoreDefs.h"
+
+_LIT( KEqual,          " = "  );
+_LIT( KNotEqual,       " <> " );
+_LIT( KGreaterOrEqual, " >= " );
+_LIT( KLessThan,       " < "  );
+
+const TUint KQuerrySize = 200;
+
+// ==================================
+// CLASS: CMsgStoreSortResultRowSet
+// ==================================
+
+// ==========================================================================
+// FUNCTION: NewL
+// ==========================================================================
+CMsgStoreSortResultRowSet* CMsgStoreSortResultRowSet::NewL( const TMsgStoreSortCriteria& aSortCriteria,
+                                                            TInt aMessageIdColNum,
+                                                            TInt aReceivedDateColNum,
+                                                            TInt aReadUnreadColNum,
+                                                            TInt aPriotiryColNum,
+                                                            TInt aFlagStatusColNum,
+                                                            TInt aSizeColNum,
+                                                            TInt aAttachmentFlagColNum )
+	{
+	CMsgStoreSortResultRowSet* self = new(ELeave) CMsgStoreSortResultRowSet( aSortCriteria, 
+	                                                                         aMessageIdColNum,
+	                                                                         aReceivedDateColNum,
+	                                                                         aReadUnreadColNum,
+	                                                                         aPriotiryColNum,
+	                                                                         aFlagStatusColNum,
+	                                                                         aSizeColNum,
+	                                                                         aAttachmentFlagColNum );
+	CleanupStack::PushL( self );
+	self->ConstructL();
+	CleanupStack::Pop( self );
+	return self;
+	}
+		
+// ==========================================================================
+// FUNCTION: Constructor
+// ==========================================================================
+CMsgStoreSortResultRowSet::CMsgStoreSortResultRowSet( const TMsgStoreSortCriteria& aSortCriteria,
+                                                      TInt aMessageIdColNum,
+                                                      TInt aReceivedDateColNum,
+                                                      TInt aReadUnreadColNum,
+                                                      TInt aPriotiryColNum,
+                                                      TInt aFlagStatusColNum,
+                                                      TInt aSizeColNum,
+                                                      TInt aAttachmentFlagColNum )
+: iIsAutoRefresh( ETrue ), iMessageIdColNum( aMessageIdColNum ), iReceivedDateColNum(aReceivedDateColNum), 
+  iReadUnreadColNum(aReadUnreadColNum), iPriotiryColNum(aPriotiryColNum), iFlagStatusColNum(aFlagStatusColNum), iSizeColNum(aSizeColNum), 
+  iAttachmentFlagColNum(aAttachmentFlagColNum)
+	{
+    __LOG_CONSTRUCT( "msg", "CMsgStoreSortResultRowSet" )
+    __LOG_CLOSE_BETWEEN_WRITES
+    
+    iMailBoxId = aSortCriteria.iMailBoxId;
+    iFolderId = aSortCriteria.iFolderId;
+    iSortBy = aSortCriteria.iSortBy; 
+    iSortOrder = aSortCriteria.iSortOrder;
+	}
+
+// ==========================================================================
+// FUNCTION: Destructor
+// ==========================================================================
+CMsgStoreSortResultRowSet::~CMsgStoreSortResultRowSet()
+	{
+    iPropertyNames.ResetAndDestroy();
+    //iSubjectPrefixToIgnore.ResetAndDestroy();
+	iDbView.Close();
+    __LOG_DESTRUCT  
+	}
+
+// ==========================================================================
+// FUNCTION: ConstructL
+// ==========================================================================
+void CMsgStoreSortResultRowSet::ConstructL()
+	{
+	}
+
+// ==========================================================================
+// FUNCTION: ToTopL
+// ==========================================================================
+void CMsgStoreSortResultRowSet::ToTopL()
+	{
+	iDbView.BeginningL();
+	}
+
+// ==========================================================================
+// FUNCTION: ToEndL
+// ==========================================================================
+void CMsgStoreSortResultRowSet::ToEndL()
+	{
+	iDbView.EndL();
+	}
+
+// ==========================================================================
+// FUNCTION: HasMorePreviousL
+// ==========================================================================
+TBool CMsgStoreSortResultRowSet::HasMorePreviousL()
+	{
+	TBool hasMorePrevious = !iDbView.AtBeginning();
+	if ( hasMorePrevious )
+	    {
+	    //if PreviousL() returns false, that means no more previous
+	    if ( !iDbView.PreviousL() )
+	        {
+	        hasMorePrevious = EFalse;
+	        }
+	    //move it back
+	    iDbView.NextL();
+	    }    
+	return hasMorePrevious;
+	}
+
+// ==========================================================================
+// FUNCTION: HasMoreNextL
+// ==========================================================================
+TBool CMsgStoreSortResultRowSet::HasMoreNextL()
+	{
+	TBool hasMoreNext = !iDbView.AtEnd();
+    if ( hasMoreNext )
+        {
+        //if NextL() returns false, that means no more next
+        if ( !iDbView.NextL() )
+            {
+            hasMoreNext = EFalse;
+            }
+        //move it back
+        iDbView.PreviousL();
+        }    
+    return hasMoreNext;
+	}
+
+// ==========================================================================
+// FUNCTION: NextL
+// ==========================================================================
+TMsgStoreId CMsgStoreSortResultRowSet::NextL()
+	{
+	iDbView.NextL();
+    if ( iDbView.AtEnd() )
+        {
+        User::Leave( KErrOverflow );
+        }
+	return GetRowL();
+	}
+
+// ==========================================================================
+// FUNCTION: PreviousL
+// ==========================================================================
+TMsgStoreId CMsgStoreSortResultRowSet::PreviousL()
+	{
+	iDbView.PreviousL();
+    if ( iDbView.AtBeginning() )
+        {
+        User::Leave( KErrUnderflow );
+        }
+	return GetRowL();
+	}
+
+// ==========================================================================
+// FUNCTION: GotoL
+// ==========================================================================
+void CMsgStoreSortResultRowSet::GotoL( TContainerId aMessageId )
+	{
+    
+    //check if the aMessageId is right on the cursor
+    TBool found = EFalse;
+    if ( iDbView.AtRow() )
+        {
+        iDbView.GetL();
+        if ( iDbView.ColUint32( iMessageIdColNum ) == aMessageId )
+            {
+            found = ETrue;
+            }
+        }
+    
+    if ( !found )
+        {
+        //have to search it from the begining
+        
+        TBuf<KQuerrySize> query;
+        query.Copy( KSortingTableMessageIdCol );
+        query.Append( KEqual );
+        query.AppendNum( aMessageId );
+        
+        iDbView.FirstL();
+        
+        TInt rc = iDbView.FindL( RDbRowSet::EForwards, query );
+        if ( rc < 0 )
+            {
+            User::Leave( rc );
+            }
+        }
+	}
+
+// ==========================================================================
+// FUNCTION: GotoL
+// ==========================================================================
+void CMsgStoreSortResultRowSet::GotoL( const TDesC& /*aStartWith*/, TMsgStoreIteratorDirection /*aDirection*/ )
+    {
+    User::Leave( KErrNotSupported );
+    }
+
+// ==========================================================================
+// FUNCTION: SkipCurrentGroupL - for UI "group" support
+// ==========================================================================
+TBool CMsgStoreSortResultRowSet::SkipCurrentGroupL( TMsgStoreIteratorDirection aDirection, TUint& aItemsInPreviousGroup )
+    {
+    __LOG_ENTER_SUPPRESS( "SkipCurrentGroupL" )
+    //if we are at the begining or end, return right away because there is NO "current group"
+    if ( iDbView.AtBeginning() || iDbView.AtEnd() )
+        {
+        return ETrue;
+        }
+    
+    TBuf<KQuerrySize> query;
+    TInt8   curValue = 0;
+    TUint32 curSizeValue = 0;
+    TInt64  curDateValue = 0;
+    
+    iDbView.GetL();
+    
+    switch( iSortBy )
+        {
+        case EMsgStoreSortByReceivedDate:
+            query.Copy( KSortingTableReceivedDateCol );
+            curDateValue = iDbView.ColInt64( iReceivedDateColNum );
+            break;
+        
+        case EMsgStoreSortByPriority:
+            query.Copy( KSortingTablePriorityCol );
+            curValue = iDbView.ColInt8( iPriotiryColNum );
+            break;
+        
+        case EMsgStoreSortByFlagStatus:
+            query.Copy( KSortingTableFlagStatusCol );
+            curValue = iDbView.ColInt8( iFlagStatusColNum );
+            break;
+        
+        case EMsgStoreSortByUnRead:
+            query.Copy( KSortingTableReadUnreadCol );
+            curValue = iDbView.ColInt8( iReadUnreadColNum );
+            break;
+        
+        case EMsgStoreSortBySize:
+            query.Copy( KSortingTableSizeCol );
+            curSizeValue = iDbView.ColUint32( iSizeColNum );
+            break;
+        
+        case EMsgStoreSortByAttachment:
+            query.Copy( KSortingTableAttachmentFlagCol );
+            curValue = iDbView.ColInt8( iAttachmentFlagColNum );
+            break;
+        
+        default:
+            User::Leave( KErrCorrupt );
+            break;
+        }
+    
+   
+    if ( iSortBy == EMsgStoreSortByReceivedDate )
+        {
+        TTime curTime(curDateValue);
+        const TUint bufSize = 100;
+        TBuf<bufSize> timeString;
+        _LIT( KDateTimeFormat, "%F%M/%D/%Y %H:%T:%S" );
+        curTime.FormatL( timeString, KDateTimeFormat() );
+        __LOG_WRITE_FORMAT1_INFO( "cur msg time=%S", &timeString )
+        
+        TLocale locale;
+        TTimeIntervalSeconds offset = locale.UniversalTimeOffset();
+        
+        
+        //get the local time
+        curTime += offset;
+        //change it to 0 o'clock
+        TDateTime curDT = curTime.DateTime();
+        TDateTime dayBoundary( curDT.Year(), curDT.Month(), curDT.Day(), 0, 0, 0, 0 );
+        TTime timeBoundary( dayBoundary );
+        //change it back to UTC
+        timeBoundary -= offset;
+        
+        timeBoundary.FormatL( timeString, KDateTimeFormat() );
+        __LOG_WRITE_FORMAT1_INFO( "timeBoundary=%S", &timeString )
+        
+        //We are search from earlier date to find the next date if 
+        //    1) sort order is ASCENDING and movinf FORWARD, or
+        //    2) sort order is DESCENDING and moving BACKWARD
+        //We are search from later date to find the previous date if
+        //    1) sort order is DESCENDING and moving FORWARD, or
+        //    2) sort order is ASCENDING and moving BACKWARD
+        if ( ( iSortOrder == EMsgStoreSortAscending && aDirection == EMsgStoreIteratorForward ) ||
+             ( iSortOrder == EMsgStoreSortDescending && aDirection == EMsgStoreIteratorBackward ) )
+            {
+            //search the next date, 
+            //so add one day to the search criteria and
+            TTimeIntervalDays day(1);
+            timeBoundary += day;
+            query.Append( KGreaterOrEqual );
+            query.AppendNum( timeBoundary.Int64() );
+            }
+        else
+            {
+            //search for previous date, use less than current date
+            query.Append( KLessThan );
+            query.AppendNum( timeBoundary.Int64() );
+            }        
+        }
+    else if ( iSortBy == EMsgStoreSortBySize )
+        {
+        query.Append( KNotEqual );
+        query.AppendNum( curSizeValue );
+        }
+    else
+        {
+        query.Append( KNotEqual );
+        query.AppendNum( curValue );
+        }
+    
+    TInt rc = KErrNone;
+    TBool hasMore = ETrue;
+    
+    if ( aDirection == EMsgStoreIteratorForward )
+        {
+        rc = iDbView.FindL( RDbRowSet::EForwards, query );
+        }
+    else
+        {
+        rc = iDbView.FindL( RDbRowSet::EBackwards, query );
+        }
+    
+    if ( rc >= 0 )
+        {
+        aItemsInPreviousGroup = rc;
+        if ( aDirection == EMsgStoreIteratorForward )
+            {
+            PreviousL();
+            }
+        else
+            {
+            NextL();
+            }
+        }
+    else
+        {
+        hasMore = EFalse;
+        }
+    
+    return hasMore;    
+    }
+
+// ==========================================================================
+// FUNCTION: GroupCountL
+// ==========================================================================
+TInt CMsgStoreSortResultRowSet::GroupCountL( RArray<TUint>& aItemsInGroup )
+    {
+    TInt count = 0;
+    TUint itemsInPreviousGroup;
+    TBool hasMore = EFalse;
+    
+    iDbView.BeginningL();
+    
+    TInt curTotal = 0;
+    
+    do { 
+        if ( !iDbView.NextL() )
+            {
+            break;
+            }
+    
+        itemsInPreviousGroup = 0;
+        hasMore = SkipCurrentGroupL( EMsgStoreIteratorForward, itemsInPreviousGroup );
+        
+        if ( itemsInPreviousGroup > 0 )
+            {
+            ++count;
+            curTotal += itemsInPreviousGroup;
+            aItemsInGroup.Append( itemsInPreviousGroup );
+            }
+        } while ( hasMore );        
+    
+    //since we can't get the item counts in the last group, we need to check if there is a last group
+    // the we may have missed
+    TInt lastGroupCount = iDbView.CountL() - curTotal;
+    if ( lastGroupCount > 0 )
+        {
+        ++count;
+        aItemsInGroup.Append( lastGroupCount );
+        }
+    
+    return count;
+    }
+
+
+// ==========================================================================
+// FUNCTION: SortedIdsL
+// ==========================================================================
+void CMsgStoreSortResultRowSet::SortedIdsL( RArray<TContainerId>& aIdArray )
+	{
+	aIdArray.Reset();
+	TInt count = iDbView.CountL();
+	iDbView.BeginningL();
+	for ( TInt i = 0 ; i < count ; i++  )
+		{
+		iDbView.NextL();
+		aIdArray.Append( GetRowL() );
+		}
+	}
+
+// ==========================================================================
+// FUNCTION: IndexOfL
+// ==========================================================================
+TInt CMsgStoreSortResultRowSet::IndexOfL( TContainerId aMessageId )
+    {
+    //have to search it from the begining
+    const TUint bufSize = 200;
+    TBuf<bufSize> query;
+    query.Copy( KSortingTableMessageIdCol );
+    query.Append( KEqual );
+    query.AppendNum( aMessageId );
+    
+    iDbView.FirstL();
+    
+    return iDbView.FindL( RDbRowSet::EForwards, query );
+    }
+
+// ==========================================================================
+// FUNCTION: SortedIdsAndGroupCountL
+// ==========================================================================
+void CMsgStoreSortResultRowSet::SortedIdsAndGroupCountL( RArray<TContainerId>& aIdArray, RArray<TUint>& aItemsInGroup )
+    {
+    SortedIdsL( aIdArray );
+    GroupCountL( aItemsInGroup );
+    }
+
+// ==========================================================================
+// FUNCTION: SetPropertyNamesL
+// ==========================================================================
+void CMsgStoreSortResultRowSet::SetPropertyNamesL( RPointerArray<HBufC8>& aPropertyNames )
+    {
+    iPropertyNames.ResetAndDestroy();
+    for ( int i = 0 ; i < aPropertyNames.Count() ; i++ )
+        {
+        iPropertyNames.Append( aPropertyNames[i]->Des().AllocL() );
+        }
+    }
+
+// ==========================================================================
+// FUNCTION: GetRowL
+// ==========================================================================
+TMsgStoreId CMsgStoreSortResultRowSet::GetRowL()
+	{
+	iDbView.GetL();
+	TContainerId msgId = iDbView.ColUint32( iMessageIdColNum );  
+	return msgId;
+	}
+
+// ==========================================================================
+// FUNCTION: MessageUpdate
+// ==========================================================================
+void CMsgStoreSortResultRowSet::MessageUpdate ( TContainerId       /*aMessageId*/, 
+                                                TContainerId       aFolderId, 
+                                                TMsgStoreOperation aOperation,               //EMsgStoreAdd, EMsgStoreDelete, EMsgStoreUpdateProperties
+                                                TUint              aFieldsChanged,       //For EMsgStoreUpdateProperties only, combinations of TSortableFieldsMasks
+                                                const TDesC&       /*aFrom*/, 
+                                                const TDesC&       /*aTo*/, 
+                                                const TDesC&       /*aSubject*/,
+                                                TInt64             /*aDate*/)
+    {
+    TBool reEvaluate = EFalse;
+    if ( iIsAutoRefresh && iFolderId == aFolderId )
+        {
+        if ( aOperation == EMsgStoreAdd || aOperation == EMsgStoreDelete )
+            {
+            reEvaluate = ETrue;
+            }
+        else if ( aOperation == EMsgStoreUpdateProperties )
+            {
+            //if received date changed, always refresh because it's always used
+            if ( aFieldsChanged & EMaskReceivedDate > 0 )
+                {
+                reEvaluate = ETrue;
+                }
+            else
+                {
+                switch( iSortBy )
+                    {
+                    case EMsgStoreSortByPriority:
+                        if ( aFieldsChanged & EMaskPriotiry )
+                            {
+                            reEvaluate = ETrue;
+                            }
+                        break;
+                        
+                    case EMsgStoreSortByFlagStatus:
+                        if ( aFieldsChanged & EMaskFlagStatus )
+                            {
+                            reEvaluate = ETrue;
+                            }
+                        break;
+                    
+                    case EMsgStoreSortByUnRead:
+                        if ( aFieldsChanged & EMaskReadUnread )
+                            {
+                            reEvaluate = ETrue;
+                            }
+                        break;
+                    
+                    case EMsgStoreSortBySize:
+                        if ( aFieldsChanged & EMaskSize )
+                            {
+                            reEvaluate = ETrue;
+                            }
+                        break;
+                    
+                    case EMsgStoreSortByAttachment:
+                        if ( aFieldsChanged & EMaskAttachmentFlag )
+                            {
+                            reEvaluate = ETrue;
+                            }
+                        break;
+                    
+                    default:
+                        //do nothing
+                        break;
+                    }
+                }
+            }
+        }
+    if ( reEvaluate )
+        {
+        ReEvaluate();     //ignore error
+        }
+    }
+
+// ==========================================================================
+// FUNCTION: FolderDeleted
+// ==========================================================================
+void CMsgStoreSortResultRowSet::FolderDeleted ( TContainerId aFolderId )
+    {
+    if ( iIsAutoRefresh && iFolderId == aFolderId )
+        {
+        //this folder does not exist anymore.
+        //reset and re-evaluate the view
+        ReEvaluate();     //ignore error
+        }
+    }
+
+// ==========================================================================
+// FUNCTION: MailBoxDeleted
+// ==========================================================================
+void CMsgStoreSortResultRowSet::MailBoxDeleted ( TContainerId aMailBoxId )
+    {
+    if ( iIsAutoRefresh && iMailBoxId == aMailBoxId )
+        {
+        //this mail box has been deleted, so the folder does not exist anymore.
+        //reset and re-evaluate the view
+        ReEvaluate();     //ignore error
+        }
+    }
+
+// ==========================================================================
+// FUNCTION: ReEvaluate
+// ==========================================================================
+TInt CMsgStoreSortResultRowSet::ReEvaluate()
+    {
+    __LOG_ENTER_SUPPRESS( "ReEvaluate" )
+    iDbView.Reset();
+    TInt rc = iDbView.EvaluateAll();
+    if ( rc != KErrNone )
+        {
+        __LOG_WRITE_FORMAT1_ERROR("EvaluateAll() failed. rc=%d", rc)
+        }
+    return rc;
+    }