imstutils/imconversationview/imcvuiengine/src/cimcvenginemessagehandler.cpp
branchRCL_3
changeset 29 9a48e301e94b
parent 0 5e5d6b214f4f
equal deleted inserted replaced
28:3104fc151679 29:9a48e301e94b
       
     1 /*
       
     2 * Copyright (c) 2007-2008 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:  message handler class implementation
       
    15 *
       
    16 */
       
    17 
       
    18 #include "cimcvenginemessagehandler.h"
       
    19 
       
    20 #include "mimcvenginechatinterface.h"
       
    21 #include "mimcvenginemessageswriteinterface.h"
       
    22 #include "imcvlogger.h"
       
    23 #include "mimcvenginenewmessagehandler.h"
       
    24 #include "imcvenginemessageutils.h"
       
    25 #include "imcvuiliterals.h"
       
    26 
       
    27 // presence cache
       
    28 #include <presencecachereader2.h>
       
    29 
       
    30 
       
    31 #include <imfeatures.h>
       
    32 #include <imconversation.h>
       
    33 #include <imobjectfactory.h>
       
    34 #include <ximpobjectfactory.h>
       
    35 #include <imconversationinfo.h>
       
    36 #include <servicepresenceinfo.h>
       
    37 #include <avabilitytext.h>
       
    38 
       
    39 #include <apmstd.h> // KMaxDataTypeLength
       
    40 #include <utf.h>    // CnvUtfConverter
       
    41 
       
    42 // imcache  related headers
       
    43 #include    <cimcachefactory.h>
       
    44 #include	<mimcacheupdater.h>
       
    45 #include    <mimcacheeventhandler.h>
       
    46 
       
    47 #include <spsettings.h>
       
    48 #include <spentry.h>
       
    49 
       
    50 #include "cimcvengineopenchats.h"
       
    51 #include "mimcvenginebuffermemoryhandler.h"
       
    52 #include "cimcvenginestoragelistener.h"
       
    53 
       
    54 const TInt KMemorySafeValue = 1024; // One kbyte for safe memory allocation.
       
    55 
       
    56 //-----------------------------------------------------------------------------
       
    57 // CIMCVEngineMessageHandler::CIMCVEngineMessageHandler
       
    58 // ( Other items commented in header )
       
    59 //-----------------------------------------------------------------------------
       
    60 CIMCVEngineMessageHandler::CIMCVEngineMessageHandler( MIMCVEngineChatInterface& aChatInterface,
       
    61                                                       MIMCVEngineMessageCreator& aMessageCreator,
       
    62 				                                      MXIMPContext* aContext, 
       
    63 				                                      TInt aServiceId )
       
    64 	: iMessageCreator( aMessageCreator ),
       
    65  	 iChatInterface( aChatInterface ),
       
    66  	 iContext(aContext),
       
    67  	iServiceId( aServiceId )
       
    68 	{
       
    69 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::CIMCVEngineMessageHandler() start") );
       
    70 	iPresenceStatus =EUnknown; // default status
       
    71 	iServiceName = NULL;
       
    72 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::CIMCVEngineMessageHandler() end") );
       
    73 	}
       
    74 
       
    75 //-----------------------------------------------------------------------------
       
    76 // CIMCVEngineMessageHandler::~CIMCVEngineMessageHandler
       
    77 // ( Other items commented in header )
       
    78 //-----------------------------------------------------------------------------
       
    79 CIMCVEngineMessageHandler::~CIMCVEngineMessageHandler()
       
    80     {
       
    81   	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::~CIMCVEngineMessageHandler() start") );
       
    82   	delete iStorageListener;
       
    83   	
       
    84   	iObserver = NULL;
       
    85   	delete iServiceName;
       
    86   	delete iPresenceCacheReader ; 
       
    87   	if( iIMCacheUpdater )
       
    88 	  	{
       
    89 	  	iIMCacheUpdater->UnRegisterObserver(*this);	
       
    90 	  	}
       
    91 	if( iIMCacheFactory )
       
    92 		{
       
    93 		CIMCacheFactory::Release();
       
    94 		iIMCacheUpdater = NULL;
       
    95 		iIMCacheFactory = NULL;
       
    96 		}
       
    97     if(iImFeatures )
       
    98 	    {
       
    99 	    delete iImFeatures;
       
   100 	    iImFeatures = NULL;	
       
   101 	    }
       
   102     iHoldingMessages.Close();
       
   103     delete iOpenChats;
       
   104   
       
   105     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::~CIMCVEngineMessageHandler() end") );
       
   106     }
       
   107 
       
   108 //-----------------------------------------------------------------------------
       
   109 // CIMCVEngineMessageHandler::NewL
       
   110 // ( Other items commented in header )
       
   111 //-----------------------------------------------------------------------------
       
   112 CIMCVEngineMessageHandler* CIMCVEngineMessageHandler::NewL( 
       
   113 					        MIMCVEngineChatInterface& aChatInterface, 
       
   114 					        MIMCVEngineMessageCreator& aMessageCreator,
       
   115 					        MXIMPContext* aContext,
       
   116 					        TInt aServiceId,
       
   117 						    const TDesC& aOwnId)
       
   118     {
       
   119   	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::NewL() start") );
       
   120     CIMCVEngineMessageHandler* self = CIMCVEngineMessageHandler::NewLC( 
       
   121             aChatInterface, 
       
   122             aMessageCreator,
       
   123             aContext,
       
   124 		    aServiceId,
       
   125 		    aOwnId );
       
   126     CleanupStack::Pop( self );
       
   127    
       
   128     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::NewL() end") );
       
   129     return self;
       
   130     }
       
   131 
       
   132 //-----------------------------------------------------------------------------
       
   133 // CIMCVEngineMessageHandler::NewLC
       
   134 // ( Other items commented in header )
       
   135 //-----------------------------------------------------------------------------
       
   136 CIMCVEngineMessageHandler* CIMCVEngineMessageHandler::NewLC( 
       
   137 					        MIMCVEngineChatInterface& aChatInterface, 
       
   138 					        MIMCVEngineMessageCreator& aMessageCreator,
       
   139 					        MXIMPContext* aContext,
       
   140 					        TInt aServiceId,
       
   141 							const TDesC& aOwnId)
       
   142     {
       
   143     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::NewLC() start") );
       
   144     CIMCVEngineMessageHandler* self = new ( ELeave ) CIMCVEngineMessageHandler( 
       
   145             aChatInterface, 
       
   146             aMessageCreator, 
       
   147              aContext,
       
   148              aServiceId );
       
   149     CleanupStack::PushL( self );
       
   150     self->ConstructL(aOwnId);
       
   151     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::NewLC() end") );
       
   152     return self;
       
   153     }
       
   154 
       
   155 //-----------------------------------------------------------------------------
       
   156 // CIMCVEngineMessageHandler::ConstructL
       
   157 // ( Other items commented in header )
       
   158 //-----------------------------------------------------------------------------
       
   159 void CIMCVEngineMessageHandler::ConstructL( const TDesC& aOwnId )
       
   160 	{
       
   161 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::ConstructL() start") );
       
   162 	 iStorageListener = CIMCVEngineStorageListener::NewL(*this);
       
   163 	// read the service name	
       
   164 	ReadServiceNameL( iServiceId );
       
   165 	// ximp im plugin
       
   166 	if (iContext)
       
   167 		{
       
   168 	    iImFeatures = MImFeatures::NewL(iContext); 
       
   169 		}
       
   170 	//initialize the presence cache.
       
   171 	iPresenceCacheReader = MPresenceCacheReader2::CreateReaderL();													 
       
   172     iPresenceCacheReader->SetObserverForSubscribedNotifications(this);
       
   173     
       
   174     // im cache factory
       
   175     iIMCacheFactory = CIMCacheFactory::InstanceL(); 
       
   176     // im cache update interface
       
   177     iIMCacheUpdater = iIMCacheFactory->CreateUpdaterL(iServiceId, aOwnId, ETrue );//registration required (ETrue).
       
   178     iIMCacheUpdater->RegisterObserverL(*this);
       
   179     
       
   180     iOpenChats = CIMCVEngineOpenChats::NewL(*this, iChatInterface,iServiceId );
       
   181     
       
   182     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::ConstructL() end") );
       
   183 	}	
       
   184 
       
   185 // ---------------------------------------------------------
       
   186 // CIMCVEngineMessageHandler::ReadServiceNameL()
       
   187 // ---------------------------------------------------------
       
   188 //
       
   189 void CIMCVEngineMessageHandler::ReadServiceNameL(TInt aServiceId )
       
   190 	{
       
   191 	CSPSettings* settings = CSPSettings::NewLC();
       
   192 	// read service name 	
       
   193 	CSPEntry* entry = CSPEntry::NewLC();
       
   194     settings->FindEntryL( aServiceId, *entry ) ;
       
   195 
       
   196 	iServiceName = NULL;
       
   197 	iServiceName = entry->GetServiceName().AllocL();
       
   198 	CleanupStack::PopAndDestroy(2); // entry, settings	
       
   199 	}
       
   200 		
       
   201 //-----------------------------------------------------------------------------
       
   202 // CIMCVEngineMessageHandler::HandleDeliveryReportL
       
   203 // ( Other items commented in header )
       
   204 //-----------------------------------------------------------------------------
       
   205 void CIMCVEngineMessageHandler::HandleDeliveryReportL(TXIMPRequestId aOperatioCode, TInt aResult)  
       
   206 	{
       
   207 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::HandleDeliveryReportL() start") );
       
   208 	
       
   209 	TInt holdingMessages = iHoldingMessages.Count();
       
   210     MIMCVEngineMessage* message = NULL;
       
   211     // Check if holding messages hold one ready message
       
   212     for(TInt index= 0 ; index < holdingMessages && !message; ++index )
       
   213         {
       
   214         MIMCVEngineMessage* msg = iHoldingMessages[ index ];
       
   215         if(  msg->OperationCode() == aOperatioCode  )
       
   216             {
       
   217             IM_CV_LOGS(TXT("CIMCVEngineMessageHandler:: pending message index = %d "), index );
       
   218             message = msg;
       
   219             if( aResult != KErrNone )
       
   220 				{
       
   221 				IM_CV_LOGS(TXT("CIMCVEngineMessageHandler:: message failed to deliver") );
       
   222 				HandleMessageSentFailedL( *iHoldingMessages[ index ] );
       
   223 				}
       
   224 			iHoldingMessages.Remove(index);
       
   225 			NotifyOperationCompletdL(message->MessagerType(), aResult );
       
   226             }
       
   227         }
       
   228    
       
   229 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::HandleDeliveryReportL() end") );	
       
   230 	}
       
   231 //-----------------------------------------------------------------------------
       
   232 // CIMCVEngineMessageHandler::HandleIMCacheMessageEventL
       
   233 // ( Other items commented in header )
       
   234 //----------------------------------------------------------------------------- 
       
   235  void CIMCVEngineMessageHandler::HandleConnectionEventL( TIMCVConnectionState aState, TInt aReason )
       
   236       {
       
   237       if( iObserver )
       
   238           {
       
   239           iObserver->HandleConnectionEventL( iServiceId, aState, aReason );
       
   240           }
       
   241       }
       
   242 //-----------------------------------------------------------------------------
       
   243 // CIMCVEngineMessageHandler::HandleIMCacheMessageEventL
       
   244 // ( Other items commented in header )
       
   245 //-----------------------------------------------------------------------------    
       
   246 void CIMCVEngineMessageHandler::HandleIMCacheEventL(TIMCacheEventType aEvent, TAny* aChatMessage )
       
   247 	{
       
   248 	switch (aEvent)
       
   249 		{
       
   250 		case EIMCacheNewMessage:
       
   251 			{
       
   252 			if (!aChatMessage)
       
   253 				{
       
   254 				return;	
       
   255 				}
       
   256 			SIMCacheMessageData* chatMesssge =  static_cast<SIMCacheMessageData*>( aChatMessage ) ;
       
   257 			
       
   258 			MIMCVEngineMessage::TMessageType messageType =  GetEngineMessageType( chatMesssge->iMessageType ) ;
       
   259 			MIMCVEngineMessage::TMessagerType messagerType = GetEngineMessagerType( chatMesssge->iMessagerType );
       
   260 			MIMCVEngineMessage::TContentType contentType = GetEngineContentType( chatMesssge->iContentType ) ;
       
   261 				
       
   262 			IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::HandleIMCacheMessageEventL() Msg ") );
       
   263 				
       
   264 			TTime time = chatMesssge->iTime;
       
   265 		
       
   266 			TPtrC buddyId = chatMesssge->iBuddyId->Des();
       
   267 		
       
   268 			if ( buddyId != KNullDesC )
       
   269 		        {
       
   270 		        
       
   271 		        if( !iChatInterface.MemoryHandler().FreeMemoryIfNeededL( KMemorySafeValue + chatMesssge->iText->Size() ) )
       
   272 		            {
       
   273 		            //NotifyMessageError( KErrNoMemory, NULL );
       
   274 		            User::Leave( KErrNoMemory );
       
   275 		            }
       
   276 		        }
       
   277 				
       
   278 		
       
   279 			IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::HandleIMCacheMessageEventL() Msg %S"), &buddyId );
       
   280 			
       
   281 
       
   282 			MIMCVEngineMessageCreator::SMessageData data = 
       
   283 														{
       
   284 														KMessageDataVersion,
       
   285 														KNullDesC,
       
   286 														buddyId,
       
   287 														chatMesssge->iText->Des(),
       
   288 														contentType,
       
   289 														messagerType
       
   290 														};	
       
   291 			MIMCVEngineMessageWriteInterface& messageContainer = 
       
   292 		                	    iChatInterface.MessageWriteInterfaceL(iServiceId, buddyId );
       
   293 			
       
   294 			MIMCVEngineMessage* message	= iMessageCreator.CreateMessageL( data );	
       
   295 			message->SetTimeStamp(time);
       
   296 			   
       
   297 			// Add message
       
   298 			IMCVEngineMessageUtils::AppendMessageWithDateStampL( 
       
   299 			                                 *message, 
       
   300 			                                 messageContainer,
       
   301 			                                 iMessageCreator );
       
   302 			
       
   303 			
       
   304 			break;	
       
   305 			}
       
   306 		case EIMCacheNewChat:
       
   307 			{
       
   308 			if (!aChatMessage)
       
   309 				{
       
   310 				return;	
       
   311 				}
       
   312 			
       
   313 			SIMCacheChatItem* chatItem =  static_cast<SIMCacheChatItem*>( aChatMessage ) ;
       
   314 			
       
   315             iStorageListener->GetContactLinkInfoL( chatItem->iServiceId,*(chatItem->iBuddyId));
       
   316              
       
   317                   
       
   318 			MIMCVEngineMessageReadInterface& messageContainer = 
       
   319 		                	    iChatInterface.MessageReadInterfaceL( chatItem->iServiceId,
       
   320 		                                                              chatItem->iBuddyId->Des() );
       
   321 			break;	
       
   322 			}
       
   323 		case EIMCacheChatClosed:
       
   324 			{
       
   325 			if (!aChatMessage)
       
   326 				{
       
   327 				return;	
       
   328 				}
       
   329 			SIMCacheChatItem* chatItem =  static_cast<SIMCacheChatItem*>( aChatMessage ) ;
       
   330 			iChatInterface.DeleteChatL( chatItem->iServiceId, chatItem->iBuddyId->Des() );						
       
   331 			break;	
       
   332 			}
       
   333 		case EIMCacheAllChatClosed:
       
   334 		    {
       
   335 			IM_CV_LOGS  (TXT("CIMCVEngineMessageHandler :: HandleChatList Event AL CHAT DELETED"));
       
   336 			iChatInterface.CloseAllContainers();                     
       
   337 		    break;  
       
   338 		    }
       
   339 		case EIMCacheRequestCompleted :
       
   340 			{
       
   341 			NotifyOperationCompletdL(MIMCVEngineMessage::EMessageStarted,  KErrNone ) ;
       
   342 			break;	
       
   343 			}	
       
   344 		default:
       
   345 			break;
       
   346 						
       
   347 		}
       
   348 	                                
       
   349 	}
       
   350 
       
   351 //-----------------------------------------------------------------------------
       
   352 // CIMCVEngineMessageHandler::GetEngineMessageType
       
   353 // ( Other items commented in header )
       
   354 //-----------------------------------------------------------------------------    
       
   355 MIMCVEngineMessage::TMessageType  CIMCVEngineMessageHandler::GetEngineMessageType(TIMCacheMessageType aType )
       
   356 	{
       
   357 	MIMCVEngineMessage::TMessageType messageType = MIMCVEngineMessage::EMessageInvalid;
       
   358 	switch( aType )
       
   359 		{
       
   360 		case EIMCMessagePTOP:
       
   361 			{
       
   362 			messageType = MIMCVEngineMessage::EMessagePTOP;
       
   363 			break;	
       
   364 			}
       
   365 		case EIMCMessageSystem:
       
   366 			{
       
   367 			messageType = MIMCVEngineMessage::EMessageSystem;
       
   368 			break;	
       
   369 			}
       
   370 		default :
       
   371 			{
       
   372 			break;	
       
   373 			}
       
   374 		}
       
   375 	return messageType;
       
   376 	}
       
   377 //-----------------------------------------------------------------------------
       
   378 // CIMCVEngineMessageHandler::GetEngineMessagerType
       
   379 // ( Other items commented in header )
       
   380 //-----------------------------------------------------------------------------    	
       
   381 MIMCVEngineMessage::TMessagerType CIMCVEngineMessageHandler::GetEngineMessagerType(TIMCacheMessagerType aType )
       
   382 	{
       
   383 	MIMCVEngineMessage::TMessagerType messagerType = MIMCVEngineMessage::EMessageOther;
       
   384 	switch( aType )
       
   385 		{
       
   386 		case EIMCMessageSent:
       
   387 			{
       
   388 			messagerType = MIMCVEngineMessage::EMessageSent;
       
   389 			break;	
       
   390 			}
       
   391 		case EIMCMessageReceived:
       
   392 			{
       
   393 			messagerType = MIMCVEngineMessage::EMessageReceived;
       
   394 			break;	
       
   395 			}
       
   396 		default :
       
   397 			{
       
   398 			break;	
       
   399 			}
       
   400 		}
       
   401 	return messagerType;
       
   402 	}
       
   403 //-----------------------------------------------------------------------------
       
   404 // CIMCVEngineMessageHandler::GetEngineContentType
       
   405 // ( Other items commented in header )
       
   406 //-----------------------------------------------------------------------------    
       
   407 MIMCVEngineMessage::TContentType  CIMCVEngineMessageHandler::GetEngineContentType(TIMCacheContentType aType )
       
   408 	{
       
   409 	MIMCVEngineMessage::TContentType contentType = MIMCVEngineMessage::EContentInvalid;
       
   410 	switch( aType )
       
   411 		{
       
   412 		case EIMCContentText:
       
   413 			{
       
   414 			contentType = MIMCVEngineMessage::EContentText;
       
   415 			break;	
       
   416 			}
       
   417 		case EIMCContentOther:
       
   418 			{
       
   419 			contentType = MIMCVEngineMessage::EContentOther;
       
   420 			break;	
       
   421 			}
       
   422 		default :
       
   423 			{
       
   424 			break;	
       
   425 			}
       
   426 		}
       
   427 	return contentType;
       
   428 	}
       
   429 
       
   430 //-----------------------------------------------------------------------------
       
   431 // CIMCVEngineMessageHandler::MessageCreator
       
   432 // ( Other items commented in header )
       
   433 //-----------------------------------------------------------------------------    
       
   434 MIMCVEngineMessageCreator& CIMCVEngineMessageHandler::MessageCreator() const
       
   435     {
       
   436     return iMessageCreator;
       
   437     }
       
   438 //-----------------------------------------------------------------------------
       
   439 // CIMCVEngineMessageHandler::StartNewConversationL
       
   440 // ( Other items commented in header )
       
   441 //-----------------------------------------------------------------------------    
       
   442 void CIMCVEngineMessageHandler::StartNewConversationL(const TDesC& aRecipientId )
       
   443 	{
       
   444 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::StartNewConversationL() start") );
       
   445 	if(iIMCacheUpdater)
       
   446 		{
       
   447 		iIMCacheUpdater->StartNewConversationL(aRecipientId);
       
   448 		}
       
   449 
       
   450 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::StartNewConversationL() end") );
       
   451 	}
       
   452   
       
   453  //-----------------------------------------------------------------------------
       
   454 // CIMCVEngineMessageHandler::CloseConversationL
       
   455 // ( Other items commented in header )
       
   456 //-----------------------------------------------------------------------------    
       
   457 TInt CIMCVEngineMessageHandler::CloseConversationL(const TDesC& aBuddyId )
       
   458 	{
       
   459 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::CloseConversationL() start ") );
       
   460 	if(iIMCacheUpdater)
       
   461 		{
       
   462 		iIMCacheUpdater->CloseConversationL( aBuddyId );;
       
   463 		}
       
   464 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::CloseConversation () %S ************"), &aBuddyId);
       
   465 	UnSubscribePresenceL (aBuddyId);
       
   466 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::CloseConversationL() end ") );
       
   467 	return KErrNone;
       
   468 	} 
       
   469 //-----------------------------------------------------------------------------
       
   470 // CIMCVEngineMessageHandler::CloseAllConversationL
       
   471 // ( Other items commented in header )
       
   472 //-----------------------------------------------------------------------------    
       
   473 void CIMCVEngineMessageHandler::CloseAllConversationL()
       
   474     {
       
   475     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::CloseAllConversationL() start") );
       
   476     iPresenceStatus = EOffline;
       
   477     if(iIMCacheUpdater  )
       
   478         {
       
   479         iIMCacheUpdater->CloseAllConversationL();
       
   480         }
       
   481 	TInt count = iOpenChats->Count ();
       
   482 
       
   483 	for (TInt i = 0; i < count; i++)
       
   484 		{
       
   485 			IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::CloseAllConversationL() CLOSING %d, CHAT ************"), i );
       
   486 			UnSubscribePresenceL (iOpenChats->GetTargetIdL (i));
       
   487 		}
       
   488     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::CloseAllConversationL() end") );
       
   489     } 
       
   490 //-----------------------------------------------------------------------------
       
   491 // CIMCVEngineMessageHandler::DeactivateConversationL
       
   492 // ( Other items commented in header )
       
   493 //-----------------------------------------------------------------------------    
       
   494 TInt CIMCVEngineMessageHandler::DeactivateConversationL()
       
   495 	{
       
   496 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::DeactivateConversation()") );
       
   497 	if(iIMCacheUpdater)
       
   498 		{
       
   499 		return iIMCacheUpdater->DeactivateConversationL();
       
   500 		}
       
   501 	return KErrNone;
       
   502 	} 
       
   503 //-----------------------------------------------------------------------------
       
   504 // CIMCVEngineMessageHandler::SendMessage
       
   505 // ( Other items commented in header )
       
   506 //-----------------------------------------------------------------------------    
       
   507 void CIMCVEngineMessageHandler::SendMessageL(MIMCVEngineMessage& message )
       
   508 	{
       
   509 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::SendMessageL() start") );
       
   510 	if(iContext == NULL || iImFeatures == NULL)
       
   511 		{
       
   512 		return;	
       
   513 		}
       
   514 		
       
   515 	MXIMPObjectFactory& objFactory = iContext->ObjectFactory();
       
   516 	MImConversation& imconversation = iImFeatures->ImConversation();    
       
   517 
       
   518 	MImConversationInfo* imMessage = iImFeatures->ImObjectFactory().NewImConversationInfoLC();
       
   519 
       
   520 	MXIMPIdentity* identity = objFactory.NewIdentityLC();  
       
   521 	identity->SetIdentityL( KMsgId );
       
   522 
       
   523 	imMessage->SetMessageIdL(identity);
       
   524 
       
   525 	imMessage->SetTextMessageL( message.Text() );
       
   526 
       
   527 	CDesCArrayFlat* recipients = new ( ELeave )CDesCArrayFlat( 2 );
       
   528 	CleanupStack::PushL( recipients);  //userid's
       
   529 	recipients->AppendL( message.Recipient() );
       
   530 
       
   531 	imMessage->SetRecipientL(recipients);
       
   532 	
       
   533     TXIMPRequestId reqId = imconversation.SendMessageL(*imMessage);
       
   534     // must set operation code
       
   535     message.SetOperationCode(reqId);
       
   536     // must append message to holding until it get delivered
       
   537     iHoldingMessages.Append( &message );
       
   538     
       
   539 	CleanupStack::PopAndDestroy();// recipients
       
   540 	// ownership is transfer to ximpfw
       
   541 	CleanupStack::Pop(); //identity
       
   542 	CleanupStack::PopAndDestroy();//imMessage  
       
   543 	
       
   544 	if(iIMCacheUpdater)
       
   545 		{
       
   546 		iIMCacheUpdater->AppendSendMessageL( message.Text() );
       
   547 		}
       
   548 	
       
   549 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::SendMessageL() end") );
       
   550 	}    
       
   551   
       
   552 //-----------------------------------------------------------------------------
       
   553 // CIMCVEngineMessageHandler::AppendToCacheL
       
   554 // ( Other items commented in header )
       
   555 //-----------------------------------------------------------------------------    
       
   556 void CIMCVEngineMessageHandler::AppendToCacheL(const TDesC& aBuddyId, const TDesC& aTextMessage )
       
   557 	{
       
   558 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::AppendToCacheL() start") );
       
   559 	if(iIMCacheUpdater)
       
   560 		{
       
   561 		iIMCacheUpdater->AppendMessageL(aBuddyId, aTextMessage );
       
   562 		}
       
   563 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::AppendToCacheL() End") );
       
   564 	} 	
       
   565  //-----------------------------------------------------------------------------
       
   566 // CIMCVEngineMessageHandler::HandleMessageSentFailedL
       
   567 // ( Other items commented in header )
       
   568 //-----------------------------------------------------------------------------
       
   569 void CIMCVEngineMessageHandler::HandleMessageSentFailedL( MIMCVEngineMessage& aMessage )
       
   570     {
       
   571    	IM_CV_LOGS(TXT("CIMCVEngineMessageCreator::HandleMessageSentFailedL() end") );
       
   572     MIMCVEngineMessage* failMessage = 
       
   573     iMessageCreator.CreateFailedMessageL( &aMessage );
       
   574     CleanupDeletePushL( failMessage );
       
   575     MIMCVEngineMessageWriteInterface& messageContainer = 
       
   576         iChatInterface.MessageWriteInterfaceL(
       
   577                 0, 
       
   578                 aMessage.Recipient() );
       
   579     CleanupStack::Pop( failMessage );
       
   580     messageContainer.AppendL( failMessage );  
       
   581   
       
   582   	// text will be Failed:text 
       
   583   	if(iIMCacheUpdater)
       
   584 		{
       
   585 		iIMCacheUpdater->AppendSendMessageL( failMessage->Text() );
       
   586 		} 
       
   587     	  
       
   588     IM_CV_LOGS(TXT("CIMCVEngineMessageCreator::HandleMessageSentFailedL() end") );
       
   589     }
       
   590  //-----------------------------------------------------------------------------
       
   591 // CIMCVEngineMessageHandler::NotifyOperationCompletdL
       
   592 // ( Other items commented in header )
       
   593 //-----------------------------------------------------------------------------
       
   594  void CIMCVEngineMessageHandler::NotifyOperationCompletdL(MIMCVEngineMessage::TMessagerType aType , TInt aResult  ) 
       
   595 	 {
       
   596 	 IM_CV_LOGS(TXT("CIMCVEngineMessageCreator::NotifyOperationCompletdL() start") );
       
   597 	 if( iObserver )
       
   598         {
       
   599         iObserver->HandleOperationCompletdL(iServiceId, aType, aResult );
       
   600         }
       
   601      IM_CV_LOGS(TXT("CIMCVEngineMessageCreator::NotifyOperationCompletdL() end") );	
       
   602 	 }
       
   603  //-----------------------------------------------------------------------------
       
   604 // CIMCVEngineMessageContainer::ResetContextL
       
   605 // ( Other items commented in header )
       
   606 //-----------------------------------------------------------------------------	
       
   607 void CIMCVEngineMessageHandler::ResetContextL(MXIMPContext* aContext)
       
   608     {
       
   609     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::ResetContextL() start") );
       
   610     iContext = NULL;
       
   611     iContext = aContext;
       
   612     if(iContext)
       
   613 		{
       
   614 		delete iImFeatures;
       
   615 		iImFeatures = NULL;	
       
   616 		iImFeatures = MImFeatures::NewL(iContext);	
       
   617 		}
       
   618     else
       
   619 		{
       
   620 		if( iIMCacheUpdater )
       
   621 			{
       
   622 			iIMCacheUpdater->UnRegisterObserver(*this);	
       
   623 			}
       
   624 		if( iIMCacheFactory )
       
   625 			{
       
   626 			CIMCacheFactory::Release();
       
   627 			iIMCacheUpdater = NULL;
       
   628 			iIMCacheFactory = NULL;
       
   629 			}	
       
   630 		}
       
   631 		
       
   632     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::ResetContextL() end") );
       
   633     }
       
   634 
       
   635 
       
   636 void CIMCVEngineMessageHandler::UnSubscribePresenceL(const TDesC& aRecipientId)
       
   637 {
       
   638 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::UnSubscribePresenceL() start %S"), &aRecipientId);
       
   639 	if( !iServiceName )
       
   640 		{
       
   641 		return;	
       
   642 		}
       
   643 	iPresenceStatus = EUnknown; // default status
       
   644 		
       
   645 	HBufC* name = HBufC::NewLC( aRecipientId.Length() + iServiceName->Length() + KCVColon().Length() );
       
   646 	TPtr namePtr( name->Des() );
       
   647 	namePtr.Zero();
       
   648 
       
   649 	// append the service name followed by user id ,seperated by colon
       
   650 	namePtr.Append(*iServiceName);
       
   651 	namePtr.Append(KCVColon);
       
   652 	namePtr.Append(aRecipientId);
       
   653 	
       
   654 	
       
   655 	IM_CV_LOGS(TXT("***************CIMCVEngineMessageHandler::UnSubscribePresenceL() %S ***************************"), &(name->Des ()));
       
   656 	// subscribe for presence change notification 
       
   657 	iPresenceCacheReader->UnSubscribePresenceBuddyChangeL(*name);
       
   658 
       
   659     CleanupStack::PopAndDestroy(); //  name  
       
   660     	
       
   661 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::UnSubscribePresenceL() End") );	                                            
       
   662 }
       
   663 
       
   664 // ---------------------------------------------------------------------------
       
   665 // CIMCVEngineMessageHandler::SubscribePresenceL
       
   666 // ---------------------------------------------------------------------------
       
   667 //  
       
   668 void CIMCVEngineMessageHandler::SubscribePresenceL(const TDesC& aRecipientId)
       
   669 	{
       
   670 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::SubscribePresenceL() start %S"), &aRecipientId );
       
   671 	if( !iServiceName )
       
   672 		{
       
   673 		return;	
       
   674 		}
       
   675 	iPresenceStatus = EUnknown; // default status
       
   676 		
       
   677 	HBufC* name = HBufC::NewLC( aRecipientId.Length() + iServiceName->Length() + KCVColon().Length() );
       
   678 	TPtr namePtr( name->Des() );
       
   679 	namePtr.Zero();
       
   680 
       
   681 	// append the service name followed by user id ,seperated by colon
       
   682 	namePtr.Append(*iServiceName);
       
   683 	namePtr.Append(KCVColon);
       
   684 	namePtr.Append(aRecipientId);
       
   685 	
       
   686 	// read the cache status
       
   687 	ReadPresenceStatusL( *name );
       
   688 
       
   689 	IM_CV_LOGS(TXT("***************CIMCVEngineMessageHandler::SubscribePresenceL() %S ***************************"), &(name->Des ()));
       
   690 	// subscribe for presence change notification 
       
   691 	iPresenceCacheReader->SubscribePresenceBuddyChangeL(*name);
       
   692 
       
   693     CleanupStack::PopAndDestroy(); //  name  
       
   694     	
       
   695 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::SubscribePresenceL() End") );	                                            
       
   696 	}
       
   697 //-----------------------------------------------------------------------------
       
   698 // CIMCVEngineMessageContainer::SetPresenceObserver
       
   699 // ( Other items commented in header )
       
   700 //-----------------------------------------------------------------------------	
       
   701 void CIMCVEngineMessageHandler::SetObserver( MIMCVEngineMessageHandlerObserver* aObserver )
       
   702 	{
       
   703 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::SetPresenceObserver() start") );
       
   704 	iObserver = NULL;
       
   705 	iObserver = aObserver;
       
   706 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::SetPresenceObserver() end") );
       
   707 	}
       
   708 
       
   709 //-----------------------------------------------------------------------------
       
   710 // CIMCVEngineMessageContainer::RemovePresenceObserver
       
   711 // ( Other items commented in header )
       
   712 //-----------------------------------------------------------------------------	
       
   713 void CIMCVEngineMessageHandler::RemoveObserver()
       
   714     {
       
   715     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::RemovePresenceObserver() start") );
       
   716     iObserver = NULL;
       
   717     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::RemovePresenceObserver() end") );
       
   718     }
       
   719 // ---------------------------------------------------------------------------
       
   720 // CIMCVEngineMessageHandler::ReadPresenceStatusL
       
   721 // ---------------------------------------------------------------------------
       
   722 //  
       
   723 void CIMCVEngineMessageHandler::ReadPresenceStatusL(const TDesC& aIdentity )
       
   724 	{
       
   725 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::ReadPresenceStatusL() start") );
       
   726 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::ReadPresenceStatusL() : buddy Id = %s"), &aIdentity );
       
   727 	MPresenceBuddyInfo2* presenceInfo = iPresenceCacheReader->PresenceInfoLC( aIdentity ); //pushed into cleanup stack
       
   728 	if( presenceInfo )
       
   729 	    {
       
   730 	    MPresenceBuddyInfo2::TAvailabilityValues  availabilityEnum = presenceInfo->Availability();
       
   731         TPtrC availabilityText = presenceInfo->AvailabilityText();
       
   732 	    iPresenceStatus = ConvertPresenceCacheEnums( availabilityEnum ,availabilityText );
       
   733 	    IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::ReadPresenceStatusL():ConvertPresenceCacheEnums: %d"),iPresenceStatus);
       
   734 	    if(EUnknown ==iPresenceStatus)
       
   735 	        {
       
   736 	        GetKeyFiledsAndValuesL(*presenceInfo);
       
   737 	        IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::ReadPresenceStatusL()::GetKeyFiledsAndValuesL: %d"),iPresenceStatus);
       
   738 	        }
       
   739 	    CleanupStack::PopAndDestroy(); //presenceInfo 
       
   740 	    }
       
   741 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::ReadPresenceStatusL() End") );	                                            
       
   742 	}
       
   743 
       
   744 // ---------------------------------------------------------------------------
       
   745 // CIMCVEngineMessageHandler::HandlePresenceReadL
       
   746 // ---------------------------------------------------------------------------
       
   747 //  
       
   748 void CIMCVEngineMessageHandler::HandlePresenceReadL(TInt /*aErrorCode*/,
       
   749                     RPointerArray<MPresenceBuddyInfo2>& /*aPresenceBuddyInfoList*/)
       
   750     {
       
   751     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::HandlePresenceReadL() start") );
       
   752 	// this is notification for all budy presence 
       
   753 	// not interested for all 
       
   754 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::HandlePresenceReadL() End") );
       
   755     }	
       
   756 // ---------------------------------------------------------------------------
       
   757 // CIMCVEngineMessageHandler::HandlePresenceNotificationL
       
   758 // ---------------------------------------------------------------------------
       
   759 //  
       
   760 void CIMCVEngineMessageHandler::HandlePresenceNotificationL(TInt /*aErrorCode*/,
       
   761                             MPresenceBuddyInfo2* aPresenceBuddyInfo )
       
   762 	{
       
   763 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::HandlePresenceNotificationL() start") );	
       
   764     
       
   765 	if ( aPresenceBuddyInfo )
       
   766 	    {
       
   767 	    CleanupDeletePushL( aPresenceBuddyInfo );
       
   768 	    TPtrC xspId = aPresenceBuddyInfo->BuddyId();
       
   769 	    // extract user id from xsp id
       
   770 	    TPtrC userId = xspId.Right(xspId.Length() - iServiceName->Length() - KCVColon().Length() );
       
   771 	    
       
   772 	    // read the availability /presence state enum value 
       
   773 	    MPresenceBuddyInfo2::TAvailabilityValues  availabilityEnum = aPresenceBuddyInfo->Availability();
       
   774         TPtrC availabilityText = aPresenceBuddyInfo->AvailabilityText();
       
   775         iPresenceStatus = ConvertPresenceCacheEnums( availabilityEnum ,availabilityText);
       
   776         IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::HandlePresenceNotificationL() : status = %d "), iPresenceStatus);   
       
   777         if(EUnknown == iPresenceStatus)
       
   778 	        {
       
   779 	        GetKeyFiledsAndValuesL(*aPresenceBuddyInfo);
       
   780 	        IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::HandlePresenceNotificationL():GetKeyFiledsAndValuesL : status = %d "), iPresenceStatus); 
       
   781 	        }
       
   782 	    // check if the display is already there,
       
   783 	    // else get it from the servicetab
       
   784 	    MIMCVEngineMessageReadInterface& readContainer = 
       
   785 	                                       iChatInterface.MessageReadInterfaceL(iServiceId, userId );
       
   786 	    IM_CV_LOGS(TXT(" CIMCVEngineMessageHandler::HandlePresenceNotificationL() before if") );
       
   787 	    if(readContainer.DisplayName().Length() == 0)
       
   788 	        {
       
   789 	        
       
   790 	        // before informing ui about the hnages,
       
   791             // create the chat if it is already not created,
       
   792             // hence we can always have the first name and the contact link before ui gets notified.
       
   793 	        IM_CV_LOGS(TXT("1 CIMCVEngineMessageHandler::HandlePresenceNotificationL() before call GetContactLinkInfoL") );
       
   794 	        iStorageListener->GetContactLinkInfoL( iServiceId,userId );
       
   795             IM_CV_LOGS(TXT(" CIMCVEngineMessageHandler::HandlePresenceNotificationL() after call GetContactLinkInfoL uid = %S"),&userId );
       
   796 	       
       
   797 	        }
       
   798 	    IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::HandlePresenceNotificationL::GetContactLinkInfoL() End ") );
       
   799 	   if( iObserver )
       
   800 	        {
       
   801 	        iObserver->HandlePresenceChangedL( iServiceId, userId );
       
   802 	        }
       
   803 	    CleanupStack::PopAndDestroy(); // aPresenceBuddyInfo
       
   804 	    }
       
   805         
       
   806     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::HandlePresenceNotificationL() End ") );	
       
   807     }
       
   808 
       
   809 // ---------------------------------------------------------------------------
       
   810 // CIMCVEngineMessageHandler::ConvertStringToStatus
       
   811 // ---------------------------------------------------------------------------
       
   812 //  
       
   813 TIMCVOnlineStatus CIMCVEngineMessageHandler::ConvertPresenceCacheEnums(MPresenceBuddyInfo2::TAvailabilityValues  aAvailabilityEnum ,TPtrC aAvailabilityText)
       
   814     {
       
   815     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::ConvertStringToStatus() Start ") );	
       
   816    
       
   817     // convert the presence cache enums to conversation view enumvalues
       
   818     // by default if the enum doesnot match then its  TVIMPSTEnums::UnKnown
       
   819     TIMCVOnlineStatus status;
       
   820     switch( aAvailabilityEnum )
       
   821         {
       
   822         case MPresenceBuddyInfo2::EBusy:
       
   823             {
       
   824 			status  = EBusy;
       
   825 			if(0==aAvailabilityText.Compare(KAwayState))
       
   826 			    {
       
   827 			    status  = EAway;
       
   828 			    }
       
   829 			if(0==aAvailabilityText.Compare(KOnPhoneState))
       
   830 			    {
       
   831 			    status  = EOnPhone;
       
   832 			    }
       
   833 			if(0==aAvailabilityText.Compare(KDndState))
       
   834 			    {
       
   835 			    status  = EDoNotDisturb;
       
   836 			    }
       
   837             break;
       
   838             }
       
   839         case MPresenceBuddyInfo2::EAvailable:
       
   840             {
       
   841             status  = EOnline;
       
   842             break;
       
   843             }
       
   844         case MPresenceBuddyInfo2::ENotAvailable:
       
   845             {
       
   846             status  = EOffline;
       
   847             break;
       
   848             }
       
   849         case MPresenceBuddyInfo2::EUnknownAvailability:
       
   850             {
       
   851             status  = EUnknown;
       
   852 						if(0==aAvailabilityText.Compare(KInvisibleState))
       
   853 						    {
       
   854 						    status  = EInvisible;
       
   855 						    }
       
   856             break;
       
   857             }  
       
   858         default:
       
   859             {
       
   860             status  = EUnknown;
       
   861             break;
       
   862             }    
       
   863         }
       
   864 
       
   865     IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::ConvertStringToStatus() End ") );	
       
   866     return status;
       
   867     }  
       
   868 
       
   869 // ---------------------------------------------------------
       
   870 // CIMCVEngineMessageHandler::GetPresenceStatus
       
   871 // 
       
   872 // ---------------------------------------------------------	
       
   873 TIMCVOnlineStatus CIMCVEngineMessageHandler::GetPresenceStatus()
       
   874 	{
       
   875 	// current presence status
       
   876 	return iPresenceStatus;
       
   877 	}
       
   878 	
       
   879 // ---------------------------------------------------------
       
   880 // CIMCVEngineMessageHandler::GetChatListL
       
   881 // 
       
   882 // ---------------------------------------------------------	
       
   883 RArray<SIMCacheChatItem> CIMCVEngineMessageHandler::GetChatListL( TInt aServiceId )
       
   884 	{
       
   885 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::StartNewConversationL() start") );
       
   886 	
       
   887 	IM_CV_LOGS(TXT("CIMCVEngineMessageHandler::StartNewConversationL() end") );
       
   888 	
       
   889 	return iIMCacheUpdater->GetChatListL(aServiceId);
       
   890 
       
   891 	}
       
   892 
       
   893 // ---------------------------------------------------------
       
   894 // CIMCVEngineMessageHandler::OpenChats
       
   895 // 
       
   896 // ---------------------------------------------------------
       
   897 CIMCVEngineOpenChats& CIMCVEngineMessageHandler::OpenChats() 
       
   898 	{
       
   899 	return 	*iOpenChats;
       
   900 	}
       
   901 
       
   902 
       
   903 // ---------------------------------------------------------------------------
       
   904 // CIMCVEngineMessageHandler::GetKeyFiledsAndValuesL
       
   905 // ---------------------------------------------------------------------------
       
   906 //
       
   907 void CIMCVEngineMessageHandler::GetKeyFiledsAndValuesL(MPresenceBuddyInfo2& aPresenceBuddyInfo)
       
   908     {
       
   909     TPtrC8 value = aPresenceBuddyInfo.GetAnyField( KExtensionKey());
       
   910     // At any point of time fro remote and blocked contact only one of the keys
       
   911     // KPendingRequestExtensionValue/KBlockedExtensionValue will be assigned, and not both the keys.
       
   912     if(value.Compare( KPendingRequestExtensionValue) == 0 )
       
   913         {
       
   914         iPresenceStatus = EPending;
       
   915         }
       
   916     else if(value.Compare( KBlockedExtensionValue ) == 0 )
       
   917         {
       
   918         iPresenceStatus = EBlock;
       
   919         }
       
   920     else if(value.Compare( KServiceExtensionValue ) == 0)
       
   921        {
       
   922        iPresenceStatus  = EServiceOut;
       
   923        }
       
   924     else if(value.Compare( KCallForwardExtensionValue ) == 0)
       
   925        {
       
   926        iPresenceStatus  = ECallForward;
       
   927        }
       
   928     }
       
   929 // ---------------------------------------------------------------------------
       
   930 // CIMCVEngineMessageHandler::ServiceId
       
   931 // ---------------------------------------------------------------------------
       
   932 //
       
   933 TInt CIMCVEngineMessageHandler::ServiceId() const 
       
   934     {
       
   935     return iServiceId;
       
   936     }
       
   937  
       
   938 // -----------------------------------------------------------------------------
       
   939 // CIMCVEngineMessageHandler: HandleServiceBuddyDetailsFetchedL
       
   940 // -----------------------------------------------------------------------------
       
   941 //
       
   942 void CIMCVEngineMessageHandler::HandleServiceBuddyDetailsFetchedL(TInt aServiceId, 
       
   943         const TDesC& aXspId,
       
   944         const TDesC8 & aContactLink,
       
   945         const TDesC & aDisplayName ) 
       
   946     {
       
   947     IM_CV_LOGS(TXT("HandleServiceBuddyDetailsFetchedL Start") );  
       
   948     IM_CV_LOGS(TXT("HandleServiceBuddyDetailsFetchedL aName= %S"),&aDisplayName );
       
   949     IM_CV_LOGS(TXT("HandleServiceBuddyDetailsFetchedL aLink= %S"),&aContactLink);  
       
   950     MIMCVEngineMessageWriteInterface& messageContainer = 
       
   951     iChatInterface.MessageWriteInterfaceL(aServiceId, aXspId, aDisplayName, aContactLink );
       
   952     messageContainer.SetNameL(aDisplayName);
       
   953     messageContainer.SetLinkL(aContactLink);
       
   954     IM_CV_LOGS(TXT("HandleServiceBuddyDetailsFetchedL End") );  
       
   955     }
       
   956  // end of file
       
   957  
       
   958