imstutils/imconversationview/imcvuiengine/src/cimcvenginemessagecontainer.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:33:36 +0100
branchRCL_3
changeset 23 9a48e301e94b
parent 0 5e5d6b214f4f
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2007-2008 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 container class implementation
*
*/

#include "cimcvenginemessagecontainer.h"
#include "mimcvenginemessageobserver.h"
#include "mimcvenginechatinterface.h"           // KSendBufferId
#include "cimcvenginemessagebase.h"
#include <escapeutils.h>
#include "imcvuiliterals.h"
#include "imcvlogger.h"
#include <collate.h>
#include "mimcvenginebuffermemoryhandler.h"
#include "mimcvenginenewmsgobserver.h"

// needed to skip domains in domain-neutral comparison (TUint version)
const TUint KAtUInt( '@' );

// general colon needed in various places
_LIT( KColon, ":" );

// general slash needed in various places
_LIT( KSlash, "/" );

// needed to skip domains in domain-neutral comparison
_LIT( KAt, "@" );

//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::CIMCVEngineMessageContainer
// ( Other items commented in header )
//-----------------------------------------------------------------------------
CIMCVEngineMessageContainer::CIMCVEngineMessageContainer( 
                                MIMCVEngineBufferMemoryHandler& aMemoryHandler )
: iMemoryHandler( aMemoryHandler )
	{
	}

//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::~CIMCVEngineMessageContainer
// ( Other items commented in header )
//-----------------------------------------------------------------------------
CIMCVEngineMessageContainer::~CIMCVEngineMessageContainer()
	{
	

	for( TInt a( 0 ); a < iMessageContainer.Count(); ++a )
	    {
	    if( iMessageContainer[ a ]->DecreaseOwnerCount() )
	        {
	        delete iMessageContainer[ a ];
	        }
	    }	
    iMessageContainer.Reset();

	
	delete iTargetId;
	delete iBuddyDisplayName;
	delete iDecodedTargetId;
	delete iEditerMessge;
	delete iContactLink;
	}
	
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::NewL
// ( Other items commented in header )
//-----------------------------------------------------------------------------
CIMCVEngineMessageContainer* CIMCVEngineMessageContainer::NewL(
                                TInt aServiceId, 
                                const TDesC& aTargetId,
                                const TDesC& aDisplayName, 
                                const TDesC8& aContactLink,
                                MIMCVEngineBufferMemoryHandler& aMemoryHandler, 
                                TContainerType aType )
	{
	CIMCVEngineMessageContainer* self = CIMCVEngineMessageContainer::NewLC(  
	                                                        aServiceId, 
	                                                        aTargetId,
	                                                        aDisplayName, 
	                                                        aContactLink,
	                                                        aMemoryHandler, 
	                                                        aType );
	CleanupStack::Pop( self );
	return self;
	}

//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::NewLC
// ( Other items commented in header )
//-----------------------------------------------------------------------------
CIMCVEngineMessageContainer* CIMCVEngineMessageContainer::NewLC(                                  
                                 TInt aServiceId, 
                                 const TDesC& aTargetId,
                                 const TDesC& aDisplayName,
                                 const TDesC8& aContactLink,
                                 MIMCVEngineBufferMemoryHandler& aMemoryHandler, 
                                 TContainerType aType )
	{
	CIMCVEngineMessageContainer* self = 
	                       new ( ELeave ) CIMCVEngineMessageContainer( aMemoryHandler );
	CleanupStack::PushL( self );
	self->ConstructL( aServiceId, aTargetId,aDisplayName,aContactLink, aType );
	return self;
	}

//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::ConstructL
// ( Other items commented in header )
//-----------------------------------------------------------------------------
void CIMCVEngineMessageContainer::ConstructL( 
                                      TInt /*aServiceId*/, 
                                      const TDesC& aTargetId,
                                      const TDesC& aDisplayName,
                                      const TDesC8& aContactLink,
                                      TContainerType aType )
	{
 	iTargetId = aTargetId.AllocL();
 	iBuddyDisplayName = aDisplayName.AllocL();
	iContactLink = aContactLink.Alloc();
	iDecodedTargetId = EscapeUtils::EscapeDecodeL( *iTargetId );
    ResolveType( aType );   

	}	

//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::UnreadCount
// ( Other items commented in header )
//-----------------------------------------------------------------------------
TInt CIMCVEngineMessageContainer::UnreadCount( 
                    MIMCVEngineMessageReadInterface::TUnreadFilter aUnreadFilter ) const
	{
	TInt countOfAll = iMessageContainer.Count();
	TInt unreadCount = countOfAll - iUnreadOffset;
	if( aUnreadFilter != EUnreadAll )
	    {
        for( TInt a = countOfAll - 1; a >= iUnreadOffset; --a )	
            {
            if( iMessageContainer[ a ]->MessagerType() == MIMCVEngineMessage::EMessageSent )
                {
                unreadCount--;
                }
            }
	    }
    return unreadCount;
	}

//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::StoreEditerMessageL
// ( Other items commented in header )
//-----------------------------------------------------------------------------
void CIMCVEngineMessageContainer::StoreEditerMessageL(const TDesC& aEditorMessage )
	{
	if( iEditerMessge)
	    {
	    delete iEditerMessge;
	    iEditerMessge = NULL;
	    }
	iEditerMessge = aEditorMessage.AllocL();  
	}

//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::GetEditerMessage
// ( Other items commented in header )
//-----------------------------------------------------------------------------

const TDesC& CIMCVEngineMessageContainer::GetEditerMessage() 
    {
    if( iEditerMessge)
        {
        return *iEditerMessge;
        }
    return KNullDesC;
    }

//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::MessageCount
// ( Other items commented in header )
//-----------------------------------------------------------------------------
TInt CIMCVEngineMessageContainer::MessageCount() const
    {
    // Offset is index to first unread message. It is exatly same as count of
    // read messages.
    return iUnreadOffset; 
    }
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::Read
// ( Other items commented in header )
//-----------------------------------------------------------------------------
void CIMCVEngineMessageContainer::Read( TReadType aReadType, TInt aAmount /* = 0 */ )
	{
	TInt messageCount( iMessageContainer.Count() );
	TInt originalUnreadCount = UnreadCount( );
	
	switch( aReadType )
		{
		case EReadAll:
			iUnreadOffset = messageCount;
			break;
		case EReadAmount:
			iUnreadOffset+= aAmount;
			break;
		case EReadOne:
			++iUnreadOffset;
			break;
		default:		    
			return;
		}

	// Cannot be more than messageCount
	if( iUnreadOffset > messageCount )
		{
		iUnreadOffset = messageCount; 
		}
	
	// Inform observers only if unreadcount is changed.
	if( originalUnreadCount != UnreadCount() )
	    {
        if (( iChatObserver ) && (!iActiveChat))
            {
            TRAP_IGNORE( iChatObserver->HandleChatEventL( 
                                MIMCVEngineNewMsgObserver::EUnreadCountChanged ) );
            }	    
	    }
	
	}
	
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::Message
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
MIMCVEngineMessage& CIMCVEngineMessageContainer::Message( TInt aIndex ) const
	{
	//__CHAT_ASSERT_DEBUG( aIndex >= 0 && aIndex < MessageCount() );
	return *iMessageContainer[ aIndex ];
	}
	
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::ReadNextUnread
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
MIMCVEngineMessage& CIMCVEngineMessageContainer::ReadNextUnread()
	{
	//__CHAT_ASSERT_DEBUG( UnreadCount() != 0 );
    Read( EReadOne );
	return *iMessageContainer[ MessageCount() - 1 ];
	}

//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::ReadUnreadFromIndex
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
MIMCVEngineMessage& CIMCVEngineMessageContainer::ReadUnreadFromIndex( TInt aIndex )
	{
	//__CHAT_ASSERT_DEBUG( UnreadCount() != 0 );
	//__CHAT_ASSERT_DEBUG( aIndex >= 0 && aIndex < iMessageContainer.Count() );
    Read( EReadOne );
	return *iMessageContainer[aIndex];
	}
	
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::SetObserver
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
void CIMCVEngineMessageContainer::SetObserver( MIMCVEngineMessageObserver* aObserver )
	{
	iObserver = aObserver;
	}
	
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::SetObserver
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
TPtrC CIMCVEngineMessageContainer::Name() const
    {
    IM_CV_LOGS(TXT("CIMCVEngineMessageContainer::Name Start"));
    if( iBuddyDisplayName && iBuddyDisplayName->Length())
        {
        IM_CV_LOGS(TXT("to_del CIMCVEngineMessageContainer::Name iBuddyDisplayName= %S"),&(*iBuddyDisplayName) );
        //IM_CV_LOGS(TXT("to_del CIMCVEngineMessageContainer::Name iBuddyDisplayName length = %d"),iBuddyDisplayName->Length() );
        return *iBuddyDisplayName;
        }
     if( iTargetId )
         {
         IM_CV_LOGS(TXT("to_del  CIMCVEngineMessageContainer::target iTargetId= %S"), &(*iTargetId));
         return DisplayId( *iTargetId ); 
         }
     return KNullDesC();
     }
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::DisplayName
// ( Other items commented in header )
//----------------------------------------------------------------------------- 
TDesC CIMCVEngineMessageContainer::DisplayName() const
    {
    IM_CV_LOGS(TXT("CIMCVEngineMessageContainer::DisplayName Start" ));
    if( iBuddyDisplayName && iBuddyDisplayName->Length())
        {
        IM_CV_LOGS(TXT("CIMCVEngineMessageContainer::DisplayName EChatContainer: %s"), &(*iBuddyDisplayName));
        return *iBuddyDisplayName;
        }
    return KNullDesC();
    }
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::SetName
// ( Other items commented in header )
//----------------------------------------------------------------------------- 
void  CIMCVEngineMessageContainer::SetNameL(const TDesC& aDisplayName)
    {
    IM_CV_LOGS(TXT("CIMCVEngineMessageContainer::SetNameL Start"));
    //if the iBuddydisplayName is same as aDisplayName 
    // then no need to set it again.
    if(iBuddyDisplayName && (aDisplayName.Compare(*iBuddyDisplayName)!=0))
        {
        delete iBuddyDisplayName;
        iBuddyDisplayName = NULL;
        IM_CV_LOGS(TXT("CIMCVEngineMessageContainer::SetName=%S"),&aDisplayName);
        iBuddyDisplayName = aDisplayName.AllocL();
        }
    }
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::SetName
// ( Other items commented in header )
//----------------------------------------------------------------------------- 
void  CIMCVEngineMessageContainer::SetLinkL(const TDesC8& aContactLink)
    {
    IM_CV_LOGS(TXT(" CIMCVEngineMessageContainer::SetLinkL Start"));
    //if the iContactLink is same as aContactLink 
    // then no need to set it again.
    if(iContactLink && (aContactLink.Compare(*iContactLink)!=0))
        {
        delete iContactLink;
        iContactLink = NULL;
        IM_CV_LOGS(TXT(" CIMCVEngineMessageContainer::SetLinkL=%S"),&aContactLink);
        iContactLink = aContactLink.AllocL();
        }
   
    }
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::ContactLink
// ( Other items commented in header )
//----------------------------------------------------------------------------- 

TPtrC8 CIMCVEngineMessageContainer::ContactLink() const
    {
    return *iContactLink;
    }
    
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::DeleteMessage
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
void CIMCVEngineMessageContainer::DeleteMessage( TInt aIndex )
    {
    MIMCVEngineMessage* target = &Message( aIndex );
    iMessageContainer.Remove( aIndex );
    iContainerSizeInBytes -= target->SizeInBytes();
    --iUnreadOffset;
    
    if( iObserver )
        {
        iObserver->HandleMessageEvent( MIMCVEngineMessageObserver::EMessageDeleted, 
                                       aIndex );
        }
        
    if( target->DecreaseOwnerCount() )
        {
        delete target;
        }
    }
    
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::AppendL
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
void CIMCVEngineMessageContainer::AppendL( MIMCVEngineMessage* aMessage, TBool aSharedOwnership )
	{
	if( !aMessage )
		{
		User::Leave( KErrArgument );
		}
		
    if( !aSharedOwnership )
        {
	    CleanupDeletePushL( aMessage );
        }
	
	// Check memory status
	// if failes, leave with KErrNoMemory
	if( !iMemoryHandler.FreeMemoryIfNeededL( aMessage->SizeInBytes() ) )
		{
		User::Leave( KErrNoMemory );
		}	    
		
	iMessageContainer.AppendL( aMessage );
	iContainerSizeInBytes += aMessage->SizeInBytes();
	
    if( !aSharedOwnership )
        {
	    CleanupStack::Pop( aMessage );
        }

	aMessage->IncreaseOwnerCount();
	
	aMessage->SetContainerInfo( this );

    IM_CV_LOGS(TXT( "Sender %s, Recipient %s" ),                           
             &aMessage->Sender(),
             &aMessage->Recipient() );
    	                                                            
    
	if( iObserver )
		{
		iObserver->HandleMessageEvent( MIMCVEngineMessageObserver::ENewMessage );
		}
		
    if ( ( iChatObserver ) && (!iActiveChat) )
        {
        iChatObserver->HandleChatEventL( MIMCVEngineNewMsgObserver::EUnreadCountChanged, 
                                        aMessage );
        }
   }

//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::ServerAddress
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
//
TTime CIMCVEngineMessageContainer::Time()
    {
    TTime time = Time::NullTTime();
    TInt count = iMessageContainer.Count();
    if( count == 0 )
        {
        // no messages, return null
        return time;
        }
    return iMessageContainer[count - 1]->TimeStamp();
    }


	
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::Target
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
const TDesC& CIMCVEngineMessageContainer::Target() const
	{
	if( !iTargetId )
	    {
	    return KNullDesC;
	    }
	return *iTargetId;
	}
	

//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::OrderUid
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
TInt CIMCVEngineMessageContainer::OrderUid( const CIMCVEngineMessageContainer& aSourceA, 
									const CIMCVEngineMessageContainer& aSourceB )
	{
    
    // points to user part of id
    TPtrC ptrId1( aSourceA.ComparableTarget() );
    TPtrC ptrId2( aSourceB.ComparableTarget() );	

    // find out if we have domains in the ids
    TInt domainPos1( ptrId1.Locate( KAtUInt ) );
    TInt domainPos2( ptrId2.Locate( KAtUInt ) );

    TBool domainIn1( KErrNotFound != domainPos1 );
    TBool domainIn2( KErrNotFound != domainPos2 );

    // points to domains in the neutral id
    TPtrC ptrDom1( KNullDesC );
    TPtrC ptrDom2( KNullDesC );

    // points to user parts in the neutral id
    TPtrC ptrUid1( ptrId1 );
    TPtrC ptrUid2( ptrId2 );

    // separate user id parts and domain parts
    if ( domainIn1 )
        {
        ptrDom1.Set( ptrId1.Mid( domainPos1 + 1) );
        ptrUid1.Set( ptrId1.Mid( 0, domainPos1 ) );
        }

    if ( domainIn2 )
        {
        ptrDom2.Set( ptrId2.Mid( domainPos2 + 1) );
        ptrUid2.Set( ptrId2.Mid( 0, domainPos2 ) );
        }

    // Create custom collation method to ignore punctuations
    // index 0 gets the default method
    TCollationMethod collation =
        *Mem::CollationMethodByIndex( 0 );
    collation.iFlags |= TCollationMethod::EIgnoreNone;

    // domains are compared only when it is really needed
    // check if userid part is the same in both ids   
    TInt idResult = ptrUid1.CompareC( ptrUid2, KCollationLevel, &collation );

	if( idResult != 0 )
		{
		return idResult;
		}

	// id part is same, we have to compare domain

    // If domain comparison is neutral and one id is without domain
    // -> Domains are same. Other situation domainResult stays valid.
    if ( domainIn1 ^ domainIn2 )
        {
        return 0;
        }
    else
    	{
    	return ptrDom1.CompareC( ptrDom2, KCollationLevel, &collation );
    	}
    }
                                        
		
	
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::ContainerType
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
MIMCVEngineMessageReadInterface::TContainerType CIMCVEngineMessageContainer::ContainerType() const
    {
    return iContainerType;
    }
    
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::ResolveType
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
void CIMCVEngineMessageContainer::SetChatObserver( MIMCVEngineNewMsgObserver* aObserver )
    {
    iChatObserver = aObserver;
    }
    
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::ResolveType
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
void CIMCVEngineMessageContainer::ResolveType( TContainerType aType )
    {
    if( aType != ENoneContainer )
        {
        iContainerType = aType;
        }
    else if( iTargetId->Compare( KSendBufferId ) == 0 )
        {
        iContainerType = ESendContainer;
        }    
    else
        {
        iContainerType = EChatContainer;
        }
    }
    
    
        
// -----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::TargetId
// ( Other items commented in header )
// -----------------------------------------------------------------------------
//
MIMCVEngineMessageContainerInfo& CIMCVEngineMessageContainer::TargetId()
    {
    return *this;
    }
    
// -----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::Lock
// locks messagecontainer if needed.
// -----------------------------------------------------------------------------
//
void CIMCVEngineMessageContainer::Lock( TBool aLocked )
    {
    iLocked = aLocked;
    }
 
// -----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::ComparableTarget
// ( Other items commented in header )
// -----------------------------------------------------------------------------
//    
const TDesC& CIMCVEngineMessageContainer::ComparableTarget() const
    {
    if ( !iDecodedTargetId )
        {
        return KNullDesC;
        }
    return *iDecodedTargetId;
    }
    
// -----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::AllMessagesCount
// ( Other items commented in header )
// -----------------------------------------------------------------------------
//
TInt CIMCVEngineMessageContainer::AllMessagesCount() const
    {
    return iMessageContainer.Count();
    }
    
// -----------------------------------------------------------------------------
// CCABufferManager::NotifyContactForPending
// ( Other items commented in header )
// -----------------------------------------------------------------------------
//    
MIMCVEngineMessage& CIMCVEngineMessageContainer::MessageFromAll( TInt aIndex ) const
    {
	//__CHAT_ASSERT_DEBUG( aIndex >= 0 && aIndex < AllMessagesCount() );
	return *iMessageContainer[ aIndex ];
    }
    
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::DeleteMessageFromAll
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
//
void CIMCVEngineMessageContainer::DeleteMessageFromAll( TInt aIndex )
    {        
    MIMCVEngineMessage* target = &MessageFromAll( aIndex );
    iMessageContainer.Remove( aIndex );
    iContainerSizeInBytes -= target->SizeInBytes();
    if( iUnreadOffset > aIndex )
        {
        --iUnreadOffset;        
        }
    
    if( iObserver )
        {
        iObserver->HandleMessageEvent( MIMCVEngineMessageObserver::EMessageDeleted, 
                                       aIndex );
        }
        
    if( target->DecreaseOwnerCount() )
        {
        delete target;
        }
    }
    
//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::IsLocked
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
//    
TBool CIMCVEngineMessageContainer::IsLocked() const
    {
    return iLocked ;
    }

//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::ContainerSizeInBytes
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
//
TInt CIMCVEngineMessageContainer::ContainerSizeInBytes() const
    {
    return iContainerSizeInBytes;
    }


//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::SetActive
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
//
void CIMCVEngineMessageContainer::SetActive( TBool aActiveChat )    
	{
	iActiveChat = aActiveChat;		
	}    


//-----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::IsActive
// ( Other items commented in header )
//-----------------------------------------------------------------------------	
//
TBool CIMCVEngineMessageContainer::IsActive()   
	{
	return iActiveChat;		
	}    



// -----------------------------------------------------------------------------
// CIMCVEngineMessageContainer::DisplayId
// -----------------------------------------------------------------------------
//
TPtrC CIMCVEngineMessageContainer::DisplayId( const TDesC& aId, TBool aDomainHiding )
	{
	TPtrC ret( aId );

	// locate ":" for userid, groupid.
	// locate "/" for list id.
	TInt pos = aId.FindC( aDomainHiding ? KSlash : KColon );

	if ( ( pos != KErrNotFound) && ( pos != aId.Length()-1) )
		{
		// contains the special character, and it is not the last char
		// remove everything before the special char (including the char)
		ret.Set( aId.Mid( pos + 1 ) );
		}
	if( aDomainHiding)
		{
		// remove also the domain part
		TInt domainPos = ret.FindC( KAt );
		if ( ( domainPos != KErrNotFound ) && ( domainPos != 0 ) )
			 {
			 ret.Set( ret.Mid( 0, domainPos ) );
			 }

		} 

	return ret;
	}

		   
// end of file