srsf/nssvasapi/nssvascore/src/nssvascspeechitemtrainer.cpp
branchRCL_3
changeset 18 cad71a31b7fc
parent 17 8ce15fced3a6
child 19 e36f3802f733
--- a/srsf/nssvasapi/nssvascore/src/nssvascspeechitemtrainer.cpp	Thu Aug 19 09:56:14 2010 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1965 +0,0 @@
-/*
-* Copyright (c) 2004-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:  The CNssSpeechItemTrainer provides methods to train, save
-*               and delete CNssSpeechItem objects in large quantities.
-*
-*/
-
-
-/* Here is a state machine for training:
-*
-* Summary:
-*
-* Idle state
-*     |
-* Waiting state     <-------------------
-*     |                                | (loop back to waiting state)
-* ###################################  |
-* # IF NEEDED: Create lexicon state #  |
-* #            |                    #  |
-* # IF NEEDED: Create grammar state #---
-* #            |                    #
-* #       Training state            #
-* ###################################
-*     |
-* Idle state
-*
-*
-*
-* State: Idle state
-* Event: A client calls TrainTextL, 
-* Action:This induces a call to CNssSpeechItemTrainer::TrainTextDealyed().
-*
-*        The basic idea of _delayed_training_ is that several training calls
-*        are piled up before taking action. When a large number of names is
-*        trained at a time, the economies of scale are considerable.
-*
-*        So, TrainTextDelayed() adds the name to the to-be-trained list,
-*        and starts a _delay_timer_. When this delay timer has finished, the
-*        actual training starts.
-* Transition: Idle state -> Waiting state
-*
-*
-* State: Waiting state
-* Event: A client calls TrainTextL.
-* Action:The function adds the name to the to-be-trained list, and
-*        resets the timer
-*        (background: In contact synchronization via PC Suite, names are added
-*         every 1/2 seconds. We want to keep piling the names  as long as
-*         new names keep coming. Since we can't wait 50 seconds
-*         before training, the only reasonable solution is to reset the timer
-*         every time a new name arrives)
-* Transition: Waiting state -> Waiting state
-*
-*
-* State: Waiting state
-* Event: Timer finishes doing time.
-* Action:Check the preparations for training:
-*         * Has the grammar for the context been created?
-*         * Has the lexicon for the context been created?
-* CASE: Preconditions OK
-*       Action    : Send async AddVoiceTags call
-*       Transition: Waiting state -> Training state
-*
-* State: Training state
-* Event: Training finished
-* Action: Save the newly created Rule IDs to the speech items.
-*         Commit the database.
-*         Make the callbacks (success or failure) to the client.
-*
-* Transition: Check if new names were piled during traning.
-*         YES: Training state -> Waiting state
-*         NO : Training state -> Idle state
-*
-*/
-
-#include "srsfbldvariant.hrh"
-#include "nssvascspeechitemtrainer.h"
-#include "nssvasctrainingparameters.h"
-#include "nssvascvasdatabase.h"
-#include "nssvasmsavetagclient.h"
-#include "nssvasmdeletetagclient.h"
-
-#include "rubydebug.h"
-
-#include <badesca.h>
-
-#ifdef _DEBUG
-    // Used in UDEB only
-    _LIT( KSpeechItemTrainerPanic, "VasCSpeechItemTrainer" );
-#endif  // _DEBUG
-
-#define DEBUGPANIC User::Panic( KSpeechItemTrainerPanic, __LINE__ )
-#define REACT( a, b ) if ( a != KErrNone ) { b; }
-#define CHECK_NOT_NULL( a ) \
-    if ( !(a) ) \
-        { \
-        return MNssSpeechItem::EVasTrainFailed; \
-        }
-#define ALLOWED_STATES( a, b, c ) \
-    if ( iState != a && iState != b && iState != c ) \
-        { \
-        return MNssSpeechItem::EVasTrainFailed; \
-        } 
-
-// tags are buffered in the buffer that grows with this granularity
-const TInt KTagBufferGranularity = 100;
-
-// rule ids are buffered in the buffer that grows with this granularity
-const TInt KRuleIdBufferGranularity = 50;
-
-// tag ids are buffered in the buffer that grows with this granularity
-const TInt KRemoveTagIdBufferGranularity = 50;
-
-// Granularity for the array of words per sinde phrase
-const TInt KSindeWordArrayGranularity = 2;
-
-
-// Local function declarations
-TInt EnforceRuleIdCountInvariant( RArray<TUint32>& aArray, TInt aCount );
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::CNssSpeechItemTrainer
-// C++ default constructor can NOT contain any code, that
-// might leave.
-// ---------------------------------------------------------
-//
-CNssSpeechItemTrainer::CNssSpeechItemTrainer( CNssVASDatabase* aDatabase )
-: iDatabase( aDatabase ),
-  iSpeechItemBuffer       ( NULL ),
-  iSpeechItemTrainingBuffer( NULL ),
-  iGrammarIdBuffer        ( NULL ),
-  iGrammarIdDeletingBuffer( NULL ),
-  iTagBuffer(NULL)
-    {
-    // empty
-    }
-
-
-// -----------------------------------------------------------------------------
-// CNssSpeechItemTrainer::ConstructL
-// Symbian 2nd phase constructor can leave.
-// This is overloaded function for SpeechItemTrainer from database
-// -----------------------------------------------------------------------------
-//
-void CNssSpeechItemTrainer::ConstructL()
-    {
-    RUBY_DEBUG_BLOCK("CNssSpeechItemTrainer::ConstructL");
-    iActionTracker = CNssTrainingActionTracker::NewL( *this );
-
-    // Create buffer for grouping phrases in training
-    iSpeechItemBuffer = new(ELeave)RPointerArray<CNssSpeechItem>;
-    iSpeechItemTrainingBuffer = 0; // No name being currently trained.
-    }
-
-
-// -----------------------------------------------------------------------------
-// CNssSpeechItemTrainer::NewL
-// Two-phased constructor.
-// This is for new SpeechItemTrainer
-// -----------------------------------------------------------------------------
-//
-CNssSpeechItemTrainer* CNssSpeechItemTrainer::NewL( CNssVASDatabase* aDatabase )
-    {
-    RUBY_DEBUG_BLOCK( "CNssSpeechItemTrainer::NewL" );
-
-    CNssSpeechItemTrainer* self = NewLC( aDatabase );
-    CleanupStack::Pop( self );
-    return self;
-    }
-
-
-// -----------------------------------------------------------------------------
-// CNssSpeechItemTrainer::NewLC
-// Two-phased constructor.
-// This is overloaded function for SpeechItemTrainer from database
-// -----------------------------------------------------------------------------
-//
-CNssSpeechItemTrainer* CNssSpeechItemTrainer::NewLC( CNssVASDatabase* aDatabase )
-    {
-    CNssSpeechItemTrainer* self
-        = new (ELeave) CNssSpeechItemTrainer( aDatabase );
-
-    CleanupStack::PushL( self );
-    self->ConstructL();
-    return self;
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::~CNssSpeechItemTrainer
-// Delete the SpeechItemTrainer object and set the Portal's 
-// state to Terminate.
-// The Trainer does not delete the Portal, the Portal  
-// deletes itself.
-// ---------------------------------------------------------
-//
-CNssSpeechItemTrainer::~CNssSpeechItemTrainer()
-    {
-    RUBY_DEBUG0( "CNssSpeechItemTrainer::~CNssSpeechItemTrainer" );
-
-    delete iActionTracker;
-
-
-    // Buffer for grouping the MNssSpeechItems for efficient training.
-    if ( iSpeechItemBuffer )
-        {
-        iSpeechItemBuffer->Reset();
-        delete iSpeechItemBuffer;
-        }
-
-    // Names, which are being trained by CSISpeechRecognitionUtility.
-    if ( iSpeechItemTrainingBuffer )
-        {
-        iSpeechItemTrainingBuffer->Reset();
-        delete iSpeechItemTrainingBuffer;
-        }
-
-    // This buffer is sent to SRS Utility. Contains: The recognition phrase split into subwords.
-    iPhraseArray.ResetAndDestroy();
-
-    // Training parameters
-    delete iTrainingParams;
-
-    // Context
-    delete iContext;
-
-    // Rule ID array. Return values from AddVoiceTags() are placed here.
-    if ( iRuleIDArray )
-        {
-        iRuleIDArray->Close();
-        delete iRuleIDArray;
-        }
-      
-    if ( iDeleteRuleIDArray )
-    	{
-        RUBY_DEBUG0( "CNssSpeechItemTrainer::~CNssSpeechItemTrainer Deleting iDeleteRuleIDArray" );
-    	iDeleteRuleIDArray->Close();
-    	delete iDeleteRuleIDArray;
-    	}
-
-    // Handle to speech services
-    if ( iSrsApi )
-        {
-        iSrsApi->CancelUtility();
-        delete iSrsApi;
-        iSrsApi = NULL;
-        }
-
-    // The tags to be saved: Owned by client
-    // RPointerArray<CNssTag> *iTagBuffer;
-    if ( iTagBuffer )
-        {
-        iTagBuffer->Reset();
-        delete iTagBuffer;
-        iTagBuffer = 0;
-        }
-
-    if ( iGrammarIdBuffer )
-        {
-        iGrammarIdBuffer->Reset();
-        delete iGrammarIdBuffer;
-        iGrammarIdBuffer = 0;
-        }
-
-    if ( iGrammarIdDeletingBuffer )
-        {
-        iGrammarIdDeletingBuffer->Reset();
-        delete iGrammarIdDeletingBuffer;
-        iGrammarIdDeletingBuffer = 0;
-        }
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::RetrainTextDelayed
-// Does delayed retraining.
-// ---------------------------------------------------------
-//
-MNssSpeechItem::TNssSpeechItemResult CNssSpeechItemTrainer::RetrainTextDelayed(
-    MNssTrainTextEventHandler* aEventHandler,
-	CNssTrainingParameters*    aTrainingParams,
-    CNssSpeechItem&            aSpeechItem,
-    CNssContext&               aContext)
-    {
-    RUBY_DEBUG0( "CNssSpeechItemTrainer::RetrainTextDelayed" );
-
-    // Check parameters: 
-    // callback 
-    CHECK_NOT_NULL( aEventHandler );
-
-    // phrase to be trained
-    CHECK_NOT_NULL( aSpeechItem.Text().Length() );
-
-    // Check state
-    ALLOWED_STATES( EStateIdle, ERetrainStateWaiting, ERetrainStateRetraining );
-
-    // Check event handler
-    if ( !iTrainEventHandler )
-        {
-        iTrainEventHandler = aEventHandler;
-        }
-    else if ( iTrainEventHandler != aEventHandler )
-        {
-        return( MNssSpeechItem::EVasTrainFailed );
-        }
-
-    // The training parameters and the context 
-    // must be the same for all in the buffer.
-    TRAPD( error,
-        if ( !CheckTrainingParametersL( aTrainingParams ) ||
-             !CheckContext( aContext ) )
-            {
-            return( MNssSpeechItem::EVasTrainFailed );
-            }
-         );
-    if ( error != KErrNone )
-        {
-        return MNssSpeechItem::EVasTrainFailed;
-        }
-
-    // Buffer the training request
-
-    // Allocate buffer, if not done earlier
-    if ( !SpeechItemBufferNeeded() )
-        {
-        return( MNssSpeechItem::EVasTrainFailed );
-        }
-
-    // If this is the first tag, save Lexicon ID and Grammar ID.
-    if ( iSpeechItemBuffer->Count() == 0 )
-        {
-        iLexiconId = aContext.LexiconId();
-        iGrammarId = aContext.GrammarId();
-        }
-    else
-        {
-        // The tags after the first one must have the same Gramamr ID & Lexicon ID.
-        if ( iLexiconId != aContext.LexiconId() ||
-            iGrammarId != aContext.GrammarId() )
-            {
-            return( MNssSpeechItem::EVasTrainFailed );
-            }
-        }
-
-    // Add request to buffer
-    TInt ret = iSpeechItemBuffer->Append( &aSpeechItem );
-
-    if ( ret != KErrNone )
-        {
-        return( MNssSpeechItem::EVasTrainFailed );
-        }
-
-    // Restart timer. When the timer has waited for a defined period, the names
-    // get retrained. Timer is reseted every time RetrainTextDelayed is called.
-    //
-    // Retraining in groups is more efficient. The delay ensures this grouping.
-    switch( iState )
-        {
-        case ERetrainStateRetraining:
-            // Wait for the retraining to finish before acting.
-            break;
-
-        case EStateIdle:
-            SetState( ERetrainStateWaiting );
-            RestartTimer();
-            break;
-
-        case ERetrainStateWaiting:
-            RestartTimer();
-            break;
-
-        default:
-            return( MNssSpeechItem::EVasTrainFailed );
-        }
-
-    return( MNssSpeechItem::EVasErrorNone );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::SaveTagDelayed
-// Does delayed saving.
-// ---------------------------------------------------------
-//
-TInt CNssSpeechItemTrainer::SaveTagDelayed(
-    MNssSaveTagClient* aSaveTagClient,
-    CNssTag& aTag )
-    {
-    RUBY_DEBUG0( "CNssSpeechItemTrainer::SaveTagDelayed" );
-
-    // Check internal state: Must not be training
-    if ( this->iState != EStateIdle &&
-         this->iState != ESaveStateWaiting &&
-         this->iState != ESaveStateSaving )
-        {
-        return( KErrNotReady );
-        }
-
-    // Check arguments
-    if ( aSaveTagClient == 0  )
-        {
-        return KErrArgument;
-        }
-
-    if ( !((CNssSpeechItem*)aTag.SpeechItem())->Trained() )
-        {
-        return KErrNotReady;
-        }
-
-    // The event handler must be the same for all group-saved tags
-    if ( !iSaveEventHandler )
-        {
-        iSaveEventHandler = aSaveTagClient;
-        }
-    else if ( aSaveTagClient != iSaveEventHandler )
-        {
-        return KErrArgument;
-        }
-
-    // Buffer the saving request
-
-    // Allocate buffer, if not done earlier
-    if ( !iTagBuffer )
-        {
-        iTagBuffer = new RPointerArray<CNssTag>( KTagBufferGranularity );
-
-        if ( !iTagBuffer )
-            {
-            return KErrNoMemory;
-            }
-        }
-
-    // Add request to buffer
-    TInt ret = iTagBuffer->Append( &aTag );
-
-    if ( ret != KErrNone )
-        {
-        return( ret );
-        }
-
-    // Restart timer. When the timer has waited for a defined period, the names
-    // get saved. Timer is reseted every time SaveTagDelayed is called.
-    //
-    // Saving in groups is more efficient. The delay ensures this grouping.
-    switch( iState )
-        {
-        case ESaveStateSaving:
-            // Wait for the training to finish before acting.
-            break;
-
-        case EStateIdle:
-            SetState( ESaveStateWaiting );
-            RestartTimer();
-            break;
-
-        case ESaveStateWaiting:
-            RestartTimer();
-            break;
-
-        default:
-            return( KErrCorrupt );
-        }
-
-    return( KErrNone );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::DeleteTagDelayed
-// Does delayed deleting.
-// (other items were commented in a header)
-// ---------------------------------------------------------
-//
-TInt CNssSpeechItemTrainer::DeleteTagDelayed(
-    MNssDeleteTagClient* aDeleteTagClient,
-    CNssTag& aTag )
-    {
-    RUBY_DEBUG0( "CNssSpeechItemTrainer::DeleteTagDelayed" );
-
-    // Check internal state: Must not be doing something else
-    ALLOWED_STATES( EStateIdle, EDeleteStateWaiting, EDeleteStateDeleting );
-
-    // Check arguments
-    CHECK_NOT_NULL( aDeleteTagClient );
-
-    // The event handler must be the same for all group-deleted tags
-    if ( !iDeleteEventHandler )
-        {
-        iDeleteEventHandler = aDeleteTagClient;
-        }
-    else if ( aDeleteTagClient != iDeleteEventHandler )
-        {
-        return KErrArgument;
-        }
-
-    // Buffer the deleting request
-
-    // Allocate buffer, if not done earlier
-    if ( !SpeechItemBufferNeeded() ||
-         !GrammarIdBufferNeeded()  )
-        {
-        return( MNssSpeechItem::EVasTrainFailed );
-        }
-
-    // If this is the first tag, save the grammar id.
-    if ( iSpeechItemBuffer->Count() == 0 )
-        {
-        iGrammarId = ((CNssContext*)aTag.Context())->GrammarId();
-        if ( !iDeleteRuleIDArray ) 
-        	{
-        	iDeleteRuleIDArray = new RArray<TUint32>;
-        	if( !iDeleteRuleIDArray ) 
-        		{
-        		return KErrNoMemory;
-	        	}
-        	// no deletion. iDeleteRuleIDArray might still be used
-        	}
-//        delete iDeleteRuleIDArray; // if any
-//        iDeleteRuleIDArray = new RArray<TUint32>;
-        }
-    else
-        {
-        // subsequent tags must have the same grammar id.
-        if ( iGrammarId != ((CNssContext*)aTag.Context())->GrammarId() )
-            {
-            return( MNssSpeechItem::EVasTrainFailed );
-            }
-        }
-
-    // Add request to buffer
-    // iSpeechItemBuffer will be copied into iSpeechItemTrainingBuffer later and
-    // iSpeechItemTrainingBuffer will be used to delete tags from the VAS DB
-    TInt ret = iSpeechItemBuffer->Append( (CNssSpeechItem*)aTag.SpeechItem() );
-    if ( ret != KErrNone )
-        {
-        return( MNssSpeechItem::EVasTrainFailed );
-        }
-
-    RUBY_DEBUG1( "CNssSpeechItemTrainer::DeleteTagDelayed Adding [%d] to iDeleteRuleIDArray", 
-        ( ( CNssSpeechItem* )aTag.SpeechItem() )->RuleID() );
-
-    ret = iDeleteRuleIDArray->Append( ( ( CNssSpeechItem* )aTag.SpeechItem() )->RuleID() );
-
-    if ( ret != KErrNone )
-        {
-        RUBY_DEBUG1( "CNssSpeechItemTrainer::DeleteTagDelayed Adding to iDeleteRuleIDArray failed with error [%d]", ret );
-        return( MNssSpeechItem::EVasTrainFailed );
-        }
-
-    // Restart timer. When the timer has waited for a defined period, the names
-    // get deleted. Timer is reseted every time DeleteDagDelayed is called.
-    //
-    // Deleting in groups is more efficient. The delay ensures this grouping.
-    switch( iState )
-        {
-        case EDeleteStateDeleting:
-            // Wait for the training to finish before acting.
-            break;
-
-        case EStateIdle:
-            SetState( EDeleteStateWaiting );
-            RestartTimer();
-            break;
-
-        case EDeleteStateWaiting:
-            RestartTimer();
-            break;
-
-        default:
-            return( KErrCorrupt );
-        }
-
-    return( KErrNone );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::TrainTextDelayed
-// Does delayed training.
-// ---------------------------------------------------------
-//
-MNssSpeechItem::TNssSpeechItemResult CNssSpeechItemTrainer::TrainTextDelayed(
-    MNssTrainTextEventHandler* aEventHandler,
-	CNssTrainingParameters*    aTrainingParams,
-    CNssSpeechItem&            aSpeechItem,
-    CNssContext&               aContext)
-    {
-    RUBY_DEBUG0( "CNssSpeechItemTrainer::TrainTextDelayed" );
-
-    // Check parameters: 
-    // callback
-    CHECK_NOT_NULL( aEventHandler );
-
-    // Text is not null
-    CHECK_NOT_NULL( aSpeechItem.Text().Length() );
-
-    // Check state
-    ALLOWED_STATES( EStateIdle, ETrainStateWaiting, ETrainStateTraining );
-
-    // Check event handler
-    if ( !iTrainEventHandler )
-        {
-        iTrainEventHandler = aEventHandler;
-        }
-    else if ( iTrainEventHandler != aEventHandler )
-        {
-        return( MNssSpeechItem::EVasTrainFailed );
-        }
-
-    // The training parameters and the context 
-    // must be the same for all in the buffer.
-    TRAPD( error,
-        if ( !CheckTrainingParametersL( aTrainingParams ) ||
-             !CheckContext( aContext ) )
-            {
-            return( MNssSpeechItem::EVasTrainFailed );
-            }
-        );
-    if ( error != KErrNone )
-        {
-        return MNssSpeechItem::EVasTrainFailed;
-        }
-
-    // Buffer the training request
-    if ( !SpeechItemBufferNeeded() )
-        {
-        return( MNssSpeechItem::EVasTrainFailed );
-        }
-
-    TInt ret = iSpeechItemBuffer->Append( &aSpeechItem );
-
-    if ( ret == KErrNoMemory )
-        {
-        return( MNssSpeechItem::EVasTrainFailed );
-        }
-
-    // Restart timer. When the timer has waited for a defined period, the names
-    // get trained. Timer is reseted every time TrainTextDelayed is called.
-    //
-    // Training in groups is more efficient. The delay ensures this grouping.
-    switch( iState )
-        {
-        case ETrainStateTraining:
-            // Wait for the training to finish before acting.
-            break;
-
-        case EStateIdle:
-            SetState( ETrainStateWaiting );
-            RestartTimer();
-            break;
-
-        case ETrainStateWaiting:
-            RestartTimer();
-            break;
-
-        default:
-            return( MNssSpeechItem::EVasTrainFailed );
-        }
-
-    return( MNssSpeechItem::EVasErrorNone );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::HandleTrainError
-// Called if AddVoiceTags() call failed.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::HandleTrainError( RPointerArray<CNssSpeechItem>*& anItemArray )
-    {
-    RUBY_DEBUG0( "CNssSpeechItemTrainer::HandleTrainError" );
-
-    TInt count = anItemArray->Count();
-
-    CleanUpTraining();
-
-    // Announce the error to the client
-    for( TInt k=0; k<count; k++ )
-        {
-        iTrainEventHandler->HandleTrainComplete( KErrGeneral );
-        
-        }
-    iTrainEventHandler = NULL;
-    // All the errors reported, everything was rolled back
-    // Back tothe idle state
-    SetState( EStateIdle );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::CleanUpTrianing
-// Cleans memory allocated by training.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::CleanUpTraining(void)
-    {
-    // Delete buffered names
-    if ( iSpeechItemTrainingBuffer )
-        {
-        iSpeechItemTrainingBuffer->Close();
-        }
-    delete iSpeechItemTrainingBuffer;
-    iSpeechItemTrainingBuffer = 0;
-
-    // Delete parameters common to all names
-    delete iTrainingParams;
-    iTrainingParams = 0;
-
-    delete iContext;
-    iContext = 0;
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::DoTrainTextDelayed
-// Starts training tags. Sends the AddVoiceTags() call.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::DoTrainTextDelayed()
-    {
-    SetState( ETrainStateTraining );
-
-    // Move from speech item buffers from filling state to processing state.
-
-    // names to be trained + names to be retrained
-    iSpeechItemTrainingBuffer = iSpeechItemBuffer;
-    iSpeechItemBuffer = 0;
-
-    // Initialize iSrsApi (speech recognition utility)
-    TInt error = CreateSrsApi();
-    if ( error != KErrNone )
-        {
-        RUBY_DEBUG1( "CNssSpeechItemTrainer::DoTrainTextDelayed Creating SrsApi failed. Error [%d]", error );
-        HandleTrainError( iSpeechItemTrainingBuffer );
-        }
-    else 
-       	{
-        	
-	    __ASSERT_DEBUG( iContext->LexiconId() != KInvalidLexiconID, 
-	                    User::Panic( KSpeechItemTrainerPanic, KErrCorrupt ) );
-	    __ASSERT_DEBUG( iContext->GrammarId() != KInvalidGrammarID, 
-	                    User::Panic( KSpeechItemTrainerPanic, KErrCorrupt ) );
-
-	    // Extract texts from speech items to phrase array.
-
-	    // iPhraseArray is an array of arrays: 
-	    // 
-	    //        |-- firstname1
-	    //  tag1 -|-- lastname1
-	    //
-	    //  tag2 -|-- firstname2
-	    //        |-- lastname2
-	    iPhraseArray.ResetAndDestroy();
-
-	    // Convert speech item array to the format understood by the Utility.
-	    TInt ret = SpeechItems2Phrases( *iSpeechItemTrainingBuffer, iPhraseArray );
-	    if ( ret != KErrNone )
-	        {
-	        SendTrainingCallbacks( ret );
-	        /** @todo reengineer into signle return path
-	            @todo check that everything is cleaned up before the return */
-	        return;
-	        }
-
-	    // Initialize Rule ID array. The Utility puts the IDs
-	    // of newly created rules here.
-	    // Not using (ELeave) since this is non-leaving function (trapping of (ELeave) is not allowed).
-	    iRuleIDArray = new RArray<TUint32>;
-
-	    if ( iRuleIDArray == 0 )
-	        {
-            RUBY_DEBUG0( "CNssSpeechItemTrainer::DoTrainTextDelayed iRuleIDArray == 0" );
-
-	        HandleTrainError( iSpeechItemTrainingBuffer );
-	        }
-	    else
-	       	{
-            RUBY_DEBUG1( "CNssSpeechItemTrainer::Calling AddVoiceTags (%d names)", 
-                         iPhraseArray.Count() ); 
-	       	// allocation succeeded
-
-            TRAPD( errSinde, const RArray<RTrainingLanguageArray>& languages = 
-                                        iTrainingParams->SindeLanguagesL() );
-            
-            if ( errSinde == KErrNone )
-                {
-#ifdef __SINDE_TRAINING
-                TRAP_IGNORE(
-                    const RArray<RTrainingLanguageArray>& languages = 
-                                        iTrainingParams->SindeLanguagesL();
-    		        ret = iSrsApi->AddVoiceTags( iPhraseArray,
-                                                 languages,
-                                                 (TSILexiconID)iContext->LexiconId(),
-                                                 (TSIGrammarID)iContext->GrammarId(),
-                                                 *iRuleIDArray );
-                ); // TRAP_IGNORE
-#endif // __SINDE_TRAINING
-                }
-            else
-                {
-                // Use the old style of training if SINDE languages are not available
-		        ret = iSrsApi->AddVoiceTags( iPhraseArray,
-                                             iTrainingParams->Languages(),
-                                             (TSILexiconID)iContext->LexiconId(),
-                                             (TSIGrammarID)iContext->GrammarId(),
-                                             *iRuleIDArray );
-                }
-
-		    // error -> cleanup
-		    if ( ret != KErrNone )
-		        {
-                RUBY_DEBUG1( "CNssSpeechItemTrainer::AddVoiceTags failed(%d)", ret );
-
-		        HandleTrainComplete( ret );
-		        }  // if ret is not KErrNone
-	       	}  // if iRuleIDArray allocation succeeded
-       	}  // if SRS API was created successfully
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::DoRetrainTextDelayed
-// Starts the 1st phase of retraining,
-// which is removing old rules.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::DoRetrainTextDelayed()
-    {
-    __ASSERT_DEBUG( iSpeechItemBuffer != 0, DEBUGPANIC );
-
-    SetState( ERetrainStateRetraining );
-
-    // Move speech item buffer from filling state to processing state.
-    iSpeechItemTrainingBuffer = iSpeechItemBuffer;
-    iSpeechItemBuffer = 0;
-
-    // Initialize iSrsApi (speech recognition utility)
-    TInt error = CreateSrsApi();
-    if ( error != KErrNone )
-        {
-        RUBY_DEBUG1( "CNssSpeechItemTrainer::DoRetrainTextDelayed Creating SrsApi failed. Error [%d]", error );
-        HandleTrainError( iSpeechItemTrainingBuffer );
-        return;
-        }
-
-    // Start deleting tags
-    iTagDeleteCounter = 0;
-    DeleteNextTag();
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::DoRetrainAddVoiceTags
-// Phase 2 of retraining: Add voice tags
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::DoRetrainAddVoiceTags()
-    {
-    SetState( ERetrainStateRetraining );
-
-    // Move from speech item buffers from filling state to processing state.
-
-    __ASSERT_DEBUG( iContext->LexiconId() != KInvalidLexiconID, 
-                    User::Panic( KSpeechItemTrainerPanic, KErrCorrupt ) );
-    __ASSERT_DEBUG( iContext->GrammarId() != KInvalidGrammarID, 
-                    User::Panic( KSpeechItemTrainerPanic, KErrCorrupt ) );
-
-    // Extract texts from speech items to phrase array.
-
-    iPhraseArray.ResetAndDestroy();
-
-    // Convert speech item array to the format understood by the Utility.
-    TInt ret = SpeechItems2Phrases( *iSpeechItemTrainingBuffer, iPhraseArray );
-    if ( ret != KErrNone )
-        {
-        SendTrainingCallbacks( ret );
-        return;
-        }
-
-    // Allocate Rule ID array. The Utility fills this array.
-    // When the utility trans a name, it attaches a Rule ID to the name.
-    iRuleIDArray = new RArray<TUint32>;
-    if ( iRuleIDArray == 0 )
-        {
-        SendTrainingCallbacks( KErrNoMemory );
-        return;
-        }
-
-    RUBY_DEBUG1( "CNssSpeechItemTrainer::Retrain Calling AddVoiceTags (%d names)", 
-                 iPhraseArray.Count() );
-
-    TRAPD( errSinde, const RArray<RTrainingLanguageArray>& languages = 
-                                        iTrainingParams->SindeLanguagesL() );
-            
-    if ( errSinde == KErrNone )
-        {
-#ifdef __SINDE_TRAINING        	
-        TRAP_IGNORE(
-            const RArray<RTrainingLanguageArray>& languages = 
-                                iTrainingParams->SindeLanguagesL();
-	        ret = iSrsApi->AddVoiceTags( iPhraseArray,
-                                         languages,
-                                         (TSILexiconID)iContext->LexiconId(),
-                                         (TSIGrammarID)iContext->GrammarId(),
-                                         *iRuleIDArray );
-        ); // TRAP_IGNORE
-#endif // __SINDE_TRAINING
-        }
-    else
-        {
-        // Use the old style of training if SINDE languages are not available
-        ret = iSrsApi->AddVoiceTags( iPhraseArray,
-                                     iTrainingParams->Languages(),
-                                     (TSILexiconID)iLexiconId,
-                                     (TSIGrammarID)iGrammarId,
-                                     *iRuleIDArray );
-        }
-
-    // error -> cleanup
-    if ( ret != KErrNone )
-        {
-        RUBY_DEBUG1( "CNssSpeechItemTrainer::Retrain ERROR: AddVoiceTags(%d)", ret );
-
-        SendTrainingCallbacks( ret );
-        }
-
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::DoRetrainAddVoiceTags
-// After the new tags have been trained:
-// Announce the new rule IDs for speech items,
-// and update the rule IDs to the VAS database.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::HandleRetrainComplete( TInt aResult )
-    {
-    RUBY_DEBUG1( "CNssSpeechItemTrainer::HandleTrainComplete(%d)", aResult );
-
-    // iRuleIdArray contains the rule IDs of the newly trained tags.
-    // The following call makes sure that
-    // iRuleIdArray.Count() == iSpeechItemTrainingBuffer.Count().
-    if ( EnforceRuleIdCountInvariant( *iRuleIDArray, 
-                        iSpeechItemTrainingBuffer->Count() ) != KErrNone )
-        {
-        SendTrainingCallbacks( KErrNoMemory );
-        }
-    else
-        {
-        TInt count = iSpeechItemTrainingBuffer->Count();
-        RArray<TNssSpeechItem> ruleIdUpdateArray( KRuleIdBufferGranularity );
-
-        for( TInt itemIdx = 0; itemIdx < count; itemIdx++ )
-            {
-            CNssSpeechItem* item = (*iSpeechItemTrainingBuffer)[itemIdx];
-            TUint32    ruleID = (*iRuleIDArray)[itemIdx];
-            if ( ruleID != KInvalidRuleID )
-                {
-                // tag was trained successfully
-
-                item->DelayedTrainingComplete( ruleID );
-                
-                TNssSpeechItem flatItem;
-
-                flatItem.iRuleId = item->RuleID();
-                flatItem.iTagId  = item->TagId();
-
-                TInt ret = ruleIdUpdateArray.Append( flatItem );
-
-                if ( ret != KErrNone )
-                    {
-                    ruleIdUpdateArray.Close();
-                    SendTrainingCallbacks( KErrNoMemory );
-                    return;
-                    }
-                }
-            else
-                {
-                // training failed -> remove tag
-                iDatabase->DeleteTag( item->TagId() );
-                }   
-            }
-
-        aResult = iDatabase->UpdateTagRuleIDs( ruleIdUpdateArray );
-        ruleIdUpdateArray.Close();
-        SendTrainingCallbacks( aResult );
-        }
-
-    
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::DoSaveTags
-// Saves tags.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::DoSaveTags()
-    {
-
-    __ASSERT_DEBUG( iState == ESaveStateWaiting, DEBUGPANIC );
-
-    // Save the tags en masse
-    TInt ret = iDatabase->SaveTags( iTagBuffer );
-
-    // Next, we're going to make callbacks to the client.
-    // Before that, we have to return the object to idle state,
-    // This way, the last callback can trigger new train/save action.
-
-    // Destroy buffered tags
-    TInt count = iTagBuffer->Count();
-    iTagBuffer->Close();
-    delete iTagBuffer;
-    iTagBuffer = 0;
-
-    // Detach save tag client
-    MNssSaveTagClient* client = iSaveEventHandler;
-    iSaveEventHandler = 0;
-
-    // Make SpeechItemTrainer ready for new challenges
-    SetState( EStateIdle );
-
-    // Make callbacks
-    for ( TInt k = 0; k < count; k++ )
-        {
-        if ( ret == KErrNone )
-            {
-#ifdef _DEBUG
-            TRAPD( err, client->SaveTagCompleted( KErrNone ) );
-            __ASSERT_DEBUG( err == KErrNone, DEBUGPANIC );
-#else
-            client->SaveTagCompleted( KErrNone );
-#endif // _DEBUG
-            }
-        else
-            {
-#ifdef _DEBUG
-            TRAPD( err, client->SaveTagCompleted( KErrGeneral ) );
-            __ASSERT_DEBUG( err == KErrNone, DEBUGPANIC );
-#else
-            client->SaveTagCompleted( KErrGeneral );
-#endif // _DEBUG
-            }
-        }
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::DoDeleteTags
-// Starts tag removal.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::DoDeleteTags()
-    {
-    // NOTE: This method is never called from anywhere!
-    
-    SetState( EDeleteStateDeleting );
-
-    TInt err = CreateSrsApi();
-    if ( err != KErrNone )
-        {
-        RemoveTagsFinished( err );
-        return;
-        }
-
-    // Move Tag Buffer from filling state to processing state.
-    iSpeechItemTrainingBuffer = iSpeechItemBuffer;
-    iSpeechItemBuffer = 0;
-    iSpeechItemBuffer = new RPointerArray<CNssSpeechItem>; // New filling buffer
-    if( !iSpeechItemBuffer )
-        {
-        SendTrainingCallbacks( KErrNoMemory );
-        return;
-        }
-
-    iTagDeleteCounter = 0;
-    DeleteNextTag();
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::DoDeleteGroupedTags
-// Starts grouped tag removal.
-// Used when deleting tags without retraining.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::DoDeleteGroupedTags()
-    {
-  	RUBY_DEBUG1("CNssSpeechItemTrainer::DoDeleteGroupedTags iDeleteRuleIDArray->Count() = [%d]", iDeleteRuleIDArray->Count() );
-	SetState( EDeleteStateDeleting );
-
-    // Move Tag Buffer from filling state to processing state.
-    // We want to have this buffer != NULL so that we are able to do callbacks (with appropriate error code )
-    // in RemoveTagsFinished method even if e.g. CreateSrsApi fails. 
-    iSpeechItemTrainingBuffer = iSpeechItemBuffer;
-    iSpeechItemBuffer = 0;
-
-    TInt err = CreateSrsApi();
-    if ( err != KErrNone )
-        {
-        RemoveTagsFinished( err );
-        return;
-        }
-
-    iSpeechItemBuffer = new RPointerArray<CNssSpeechItem>; // New filling buffer
-    
-    if( !iSpeechItemBuffer )
-        {
-        // As this method is not used when retraining, no need 
-        // to send other callbacks than those related to deleting tags.
-        RemoveTagsFinished( KErrNoMemory );
-        return;
-        }
-
-	TInt ret = iSrsApi->RemoveRules( ( TSIGrammarID )iGrammarId,
-                                     *iDeleteRuleIDArray );
-
-    if ( ret != KErrNone && ret != KErrNotFound )
-        {
-        RUBY_DEBUG1( "CNssSpeechItemTrainer::DoDeleteGroupedTags RemoveRules failed. \
-                      Error [%d]", ret );
-        RemoveTagsFinished( ret );
-        return;
-        }
-
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::DeleteNextTag
-// Sends a RemoveRule() call for the next rule in the removal queue.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::DeleteNextTag()
-    {
-    RUBY_DEBUG2( "CNssSpeechItemTrainer::DeleteNextTag iTagDeleteCounter [%d], iSpeechItemTrainingBuffer->Count() [%d]", iTagDeleteCounter, iSpeechItemTrainingBuffer->Count() );
-
-    __ASSERT_DEBUG( iTagDeleteCounter <= iSpeechItemTrainingBuffer->Count(), 
-                    User::Panic( KSpeechItemTrainerPanic, __LINE__ ) );
-
-    CNssSpeechItem* speechItem = (*iSpeechItemTrainingBuffer)[iTagDeleteCounter];
-
-    TInt ret = iSrsApi->RemoveRule(
-        (TSIGrammarID)speechItem->GrammarId(),
-        (TSIRuleID)speechItem->RuleID()
-        );
-
-    if ( ret != KErrNone && ret != KErrNotFound )
-        {
-        RemoveTagsFinished( ret );
-        return;
-        }
-    }
-
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::HandleRemoveTagComplete
-// Called after SRS has successfully removed a tag.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::HandleRemoveTagComplete()
-    {
-    iTagDeleteCounter++;
-
-    if ( iTagDeleteCounter < iSpeechItemTrainingBuffer->Count() )
-        {
-        DeleteNextTag();
-        }
-    else
-        {
-        RemoveTagsFinished( KErrNone );
-        return;
-        }
-    }
-    
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::HandleRemoveTagsComplete
-// Called after SRS has successfully removed a group of tags.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::HandleRemoveTagsComplete()
-    {
-    RemoveTagsFinished( KErrNone );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::HandleRemoveTagFailed
-// Called if SRS fails to remove a tag.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::HandleRemoveTagFailed( TInt aError )
-    {
-    RemoveTagsFinished( aError );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::RemoveTagsFinished
-// All required tags have been removed.
-// Go to next phase.
-//    functions a bit defferently depending on whether we were retraining or
-//    deleting tags
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::RemoveTagsFinished( TInt aSuccess )
-    {
-    // The continuation depends on what we are doing:
-
-    // If we are deleting tags
-    if ( iState == EDeleteStateDeleting )
-        {
-        if ( aSuccess == KErrNone )
-            {
-            RemoveTagsFromVAS();
-            }
-        else{
-            FinishDeleteTags( aSuccess );
-            }
-        }
-
-    // If we are retraining 
-    // (removing the old rules before adding the new ones)
-    else if ( iState == ERetrainStateRetraining )
-        {
-        if  ( aSuccess == KErrNone )
-            {
-            DoRetrainAddVoiceTags();
-            }
-        else{
-            SendTrainingCallbacks( aSuccess );
-            }
-        }
-    else
-        {
-        RUBY_DEBUG1( "CNssSpeechItemTrainer::RemoveTagsFinished - ERROR: Wrong state(%d)", iState );
-        }
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::RemoveTagsFromVAS
-// Deletes tags from VAS.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::RemoveTagsFromVAS()
-    {
-    RArray<TUint32> tagIdArray( KRemoveTagIdBufferGranularity );
-    TInt ret = KErrNone;
-
-    ////////////// Remove tags from VAS DB ///////////////////
-
-    // Take the Tag IDs to an array.
-    for ( TInt k( 0 ); k < iSpeechItemTrainingBuffer->Count(); k++ )
-        {
-        ret |= tagIdArray.Append( (*iSpeechItemTrainingBuffer)[k]->TagId() );
-        }
-
-    // Delete tags from VAS DB
-    if ( ret == KErrNone )
-        {
-        ret = iDatabase->DeleteTags( tagIdArray );
-        }
-
-    // Close tag ID array.
-    tagIdArray.Close();
-
-    ////////////// Remove tags from VAS DB done //////////////
-
-    FinishDeleteTags( KErrNone );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::FinishDeleteTags
-// Cleans up and sends calbacks after
-// deleting has finished or completed.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::FinishDeleteTags( TInt aSuccess )
-    {
-    RUBY_DEBUG1("CNssSpeechItemTrainer::FinishDeleteTags aSuccess [%d]", aSuccess);
-    // Commit or uncommit according to success
-    if ( iSrsApi )
-        {
-        if ( aSuccess == KErrNone )
-            {
-            CommitSIUpdate();
-            }
-        else{
-            UncommitSIUpdate();
-            }
-        }
-	
-    // Free memory
-    TInt count( 0 );
-    if ( iSpeechItemTrainingBuffer )
-        {        
-        count = iSpeechItemTrainingBuffer->Count();
-        RUBY_DEBUG1("CNssSpeechItemTrainer::FinishDeleteTags aSuccess Freeing [%d] items from the training buffer", count);
-        iSpeechItemTrainingBuffer->Close();
-        }
-    delete iSpeechItemTrainingBuffer;
-    iSpeechItemTrainingBuffer = 0;
-
-    // Send callbacks
-    MNssDeleteTagClient* client = iDeleteEventHandler;
-    iDeleteEventHandler = 0;
-    iTagDeleteCounter = 0;
-
-    
-    for ( TInt k( 0 ); k < count; k++ )
-        {
-        RUBY_DEBUG1("CNssSpeechItemTrainer::FinishDeleteTags sending callback for item [%d]", k);
-        // Failed or succeedeed, one rule is processed
-        iDeleteRuleIDArray->Remove(0);
-       
-        client->DeleteTagCompleted( aSuccess );
-        }
-    RUBY_DEBUG2("CNssSpeechItemTrainer::FinishDeleteTags Reported [%d] deletions. [%d] remaining. Setting idle state", count, iDeleteRuleIDArray->Count());
-    SetState( EStateIdle );
-
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::RunBufferedActionsL
-// Called when it is time to execute the buffered actions
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::RunBufferedActionsL()
-    {
-    RUBY_DEBUG_BLOCK( "CNssSpeechItemTrainer::RunL" );
-    
-    if ( iState == ETrainStateWaiting )
-        {
-        DoTrainTextDelayed();
-        }
-    else if ( iState == ESaveStateWaiting )
-        {
-        DoSaveTags();
-        }
-    else if ( iState == EDeleteStateWaiting )
-        {
-        DoDeleteGroupedTags();
-        }
-    else if ( iState == ERetrainStateWaiting )
-        {
-        DoRetrainTextDelayed();
-        }
-    else
-        {
-        RUBY_DEBUG1( "CNssSpeechItemTrainer::RunL - ERROR: Wrong state (%d)", iState );
-        }
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::RestartTimer
-// Restarts the timer.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::RestartTimer()
-    {
-    TRAP_IGNORE( iActionTracker->ActionRequestedL() );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::CheckTrainingParametersL
-// All tags in the queue should have the same training parameters. This
-// function check that a new context has similar training parameters
-// as the previous ones.
-// ---------------------------------------------------------
-//
-TBool CNssSpeechItemTrainer::CheckTrainingParametersL( const CNssTrainingParameters* aParams )
-    {
-    if ( aParams )
-        {
-        if ( !iTrainingParams )
-            {
-            // Make a local copy of training parameters
-            iTrainingParams = CNssTrainingParameters::NewL();
-
-            const RArray<TLanguage>& paramLangArray = aParams->Languages();
-
-            RArray<TLanguage>* langArray = new ( ELeave ) RArray<TLanguage>;
-            CleanupStack::PushL( langArray );
-                
-            for ( TInt k = 0; k < paramLangArray.Count(); k++ )
-                {
-                TInt ret = langArray->Append( paramLangArray[ k ] );
-                if ( ret != KErrNone )
-                    {
-                    langArray->Close();
-                    delete langArray;
-                    return EFalse;
-                    }
-                }
-                
-            // Copy training languages
-            iTrainingParams->SetLanguages( langArray );
-            CleanupStack::Pop( langArray );
-
-            // Copy SINDE languages
-            TRAP_IGNORE( iTrainingParams->SetSindeLanguages( aParams->SindeLanguagesL() ) );
-            
-            // Copy separator
-            iTrainingParams->SetSeparator( aParams->Separator() );
-            }
-        else
-            {
-            // Compare with previous training parameters
-            
-            // Separator
-            if ( aParams->Separator() != iTrainingParams->Separator() )
-                {
-                return EFalse;
-                }
-
-            // Training languages
-            for ( TInt k = 0; k < aParams->Languages().Count(); k++ )
-                {
-                if ( aParams->Languages()[ k ] != iTrainingParams->Languages()[ k ] )
-                    {
-                    return EFalse;
-                    }
-                }
-            
-            // @todo SINDE languages should be checked also!            
-            }
-       }
-       
-    return ETrue;
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::CheckContext
-// All tags in the queue should have the same contexts. This
-// function check that a new context is similar to that of previous tags.
-// ---------------------------------------------------------
-//
-TBool CNssSpeechItemTrainer::CheckContext(CNssContext& aContext)
-    {
-    if ( &aContext == 0 ) // Default settings - anything goes.
-        {
-        return( EFalse );
-        }
-
-    if ( aContext.RecognitionMode() != ENSSSdSiMode &&
-         aContext.RecognitionMode() != ENSSSiMode )
-        {
-        return( EFalse );
-        }
-
-    if ( iContext )
-        {
-        // Check that identifiers (name & ID) are identical.
-        if ( aContext.ContextId() != iContext->ContextId() )
-            {
-            return( EFalse );
-            }
-
-        if ( aContext.ContextName().Compare( iContext->ContextName() ) != 0 )
-            {
-            return( EFalse );
-            }
-        }
-    else
-        {
-        if ( aContext.RecognitionMode()  == ENSSSdSiMode )
-            {
-            aContext.SetRecognitionMode( ENSSSiMode );
-            }
-
-        TRAPD( error, iContext = aContext.CopyL() );
-        if ( error != KErrNone )
-            {
-            return EFalse;
-            }
-        }
-
-    return( ETrue );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::HandleTrainComplete
-// Called after speech recognition utility has trained all tags.
-// Announces the newly assigned Rule IDs for the speech items.
-// Signals the VAS client that training has been finished.
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::HandleTrainComplete( TInt aResult )
-    {
-    RUBY_DEBUG1( "CNssSpeechItemTrainer::HandleTrainComplete(%d)", aResult );
-
-    // iRuleIdArray contains the rule IDs of the newly trained tags.
-    // The following call makes sure that
-    // iRuleIdArray.Count() == iSpeechItemTrainingBuffer.Count().
-    if ( EnforceRuleIdCountInvariant( *iRuleIDArray, 
-              iSpeechItemTrainingBuffer->Count() ) != KErrNone )
-        {
-        SendTrainingCallbacks( KErrNoMemory );
-        }
-
-    // Save rule IDs. Some rule IDs may have "KInvalidRuleID". This is a sign
-    // that training failed. It's good to save also that info to speech items.
-    for( TInt itemIdx = 0; itemIdx < iSpeechItemTrainingBuffer->Count(); itemIdx++ )
-        {
-        CNssSpeechItem* item = (*iSpeechItemTrainingBuffer)[ itemIdx ];
-        TUint32    ruleID = (*iRuleIDArray)[ itemIdx ];
-
-        item->DelayedTrainingComplete( ruleID );
-        }
-
-    SendTrainingCallbacks( aResult );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::SendTrainingCallbacks
-// 
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::SendTrainingCallbacks( TInt aResult )
-    {
-    // If the changes were successful, commit them.
-    // If they werent, roll back the changes.
-    if ( aResult == KErrNone )
-        {
-        CommitSIUpdate();
-        }
-    else{
-        UncommitSIUpdate();
-        }
-
-    // Save count (callback count)...
-    TInt count = iSpeechItemTrainingBuffer->Count();
-    MNssTrainTextEventHandler* callback = iTrainEventHandler;
-    RArray<TUint32>* ruleIdArray = iRuleIDArray;
-    iRuleIDArray = 0;
-
-    // Delete buffered names that were just trained
-    if ( iSpeechItemTrainingBuffer )
-        {
-        iSpeechItemTrainingBuffer->Close();
-        }
-    delete iSpeechItemTrainingBuffer;
-    iSpeechItemTrainingBuffer = 0;
-
-
-    // If there are names on the training queue,
-    // restart the waiting of delayed training.
-    if ( iSpeechItemBuffer && iSpeechItemBuffer->Count() > 0 )
-        {
-        // don't delete context etc as training will be continued
-        SetState( ETrainStateWaiting );
-        RestartTimer();
-        }
-    else
-        {
-        SetState( EStateIdle );
-            
-        // Cleanup
-        delete iTrainingParams;
-        iTrainingParams = 0;
-
-        delete iContext;
-        iContext = 0;
-        
-        iTrainEventHandler = 0;        
-        }
-
-    // Make the callbacks to the client according to the recognition result.
-    for( TInt k( 0 ); k < count; k++ )
-        {
-        if ( ruleIdArray->Count() <= k )
-            {
-            RUBY_DEBUG2( "CNssSpeechItemTrainer::SendTrainingCallbacks ruleIdArray->Count() [%d] <= k [%d]", ruleIdArray->Count(), k );
-            callback->HandleTrainComplete( KErrNoMemory );
-            }
-        if ( (*ruleIdArray)[ k ] == KInvalidRuleID )
-            {
-            RUBY_DEBUG0( "CNssSpeechItemTrainer::SendTrainingCallbacks (*ruleIdArray)[ k ] == KInvalidRuleID" );
-            if ( aResult == KErrNone )
-                {
-                callback->HandleTrainComplete( KErrGeneral );
-                }
-            else
-                {
-                callback->HandleTrainComplete( aResult );
-                }
-            
-            }
-        else
-            {
-            callback->HandleTrainComplete( KErrNone );
-            }
-        }
-
-    ruleIdArray->Close();
-    delete ruleIdArray;
-    ruleIdArray = 0;
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::MsruoEvent
-// SRS Utility callback function 
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::MsruoEvent( TUid aEvent, TInt aResult )
-    {
-    switch( aEvent.iUid )
-        {
-        case KUidAsrEventAddVoiceTagsVal:
-            RUBY_DEBUG0( "CNssSpeechItemTrainer::MsruoEvent - state is KUidAsrEventAddVoiceTagsVal" );
-
-            if ( iState == ETrainStateTraining )
-                {
-                HandleTrainComplete( aResult );
-                }
-            else if ( iState == ERetrainStateRetraining )
-                {
-                HandleRetrainComplete( aResult );
-                }
-            break;
-
-        case KUidAsrEventRemoveRuleVal:
-            RUBY_DEBUG0( "CNssSpeechItemTrainer::MsruoEvent - state is KUidAsrEventRemoveRuleVal" );
-
-            if ( aResult == KErrNone || aResult == KErrNotFound )
-                {
-                HandleRemoveTagComplete();
-                }
-            else{
-                HandleRemoveTagFailed( aResult );
-                }
-            break;
-            
-        case KUidAsrEventRemoveRulesVal:
-            RUBY_DEBUG0( "CNssSpeechItemTrainer::MsruoEvent - state is KUidAsrEventRemoveRulesVal" );
-
-        	if( aResult == KErrNone || aResult == KErrNotFound )
-        		{
-        		HandleRemoveTagsComplete();
-        		}
-        	else 
-        		{
-        		HandleRemoveTagFailed( aResult );
-        		}
-        	break;
-
-        default:
-            RUBY_DEBUG2( "CNssSpeechItemTrainer::MsruoEvent - ERROR: Uknown state (%d,%d)", aEvent.iUid, aResult );
-            break;
-        }
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::SplitPhraseSindeL
-// Splits a phrase to parts. Returns the parts in array.
-// ---------------------------------------------------------
-//
-CDesC16ArrayFlat* CNssSpeechItemTrainer::SplitPhraseSindeL( const TDesC& aPhrase, 
-                                                            TChar aSeparator )
-    {
-    CDesC16ArrayFlat* wordArray = new ( ELeave ) CDesC16ArrayFlat( KSindeWordArrayGranularity );
-    CleanupStack::PushL( wordArray );
-
-    // Separate the words in the phrase.
-    TPtrC text = aPhrase; // Cursor to the phrase
-
-    do
-        {
-        TInt index = text.Locate( aSeparator );
-
-        if ( index != 0 )
-            {
-            // no more separators -> this is the last word -> end of word == end of string
-            if ( index == KErrNotFound ) 
-                {
-                index = text.Length();
-                }
-
-                // Add word to array
-                wordArray->AppendL( text.Left( index ) );
-                }
-
-        // Discard the processed word
-        TInt charactersLeft = text.Length() - index; 
-        // Forget the separator
-        if ( charactersLeft > 0 )                    
-            {
-            charactersLeft--;                        
-            }
-
-        // Update text cursor
-        text.Set( text.Right( charactersLeft ) );
-
-        } 
-    while( text.Length() > 0 );
-
-    CleanupStack::Pop( wordArray );
-    return wordArray;
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::SplitPhrase
-// Splits a phrase to parts. Returns the parts in array.
-// ---------------------------------------------------------
-//
-CDesC16ArrayFlat* CNssSpeechItemTrainer::SplitPhraseL( const TDesC& aPhrase, TChar aSeparator )
-    {
-    CDesC16ArrayFlat *wordArray = new (ELeave) CDesC16ArrayFlat( KSindeWordArrayGranularity );
-
-    // Separate the words in the phrase. Especially firstname / lastname.
-    TPtrC text = aPhrase; // Cursor to the phrase
-
-    do
-        {
-        TInt index = text.Locate( aSeparator );
-
-        // no more separators -> this is the last word -> end of word == end of string
-        if ( index == -1 ) 
-            {
-            index = text.Length();
-            }
-
-        // Add word to array
-        wordArray->AppendL( text.Left( index ) );
-
-        // Discard the processed word
-        TInt charactersLeft = text.Length() - index; 
-        // Forget the separator
-        // (the last word doesn't have one)
-        if ( charactersLeft > 0 )                    
-            {
-            charactersLeft--;                        
-            }
-
-        // Update text cursor
-        text.Set( text.Right( charactersLeft ) );
-
-        } 
-    while( text.Length() > 0 );
-
-    return wordArray;
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::CommitSIUpdate
-// Commits changes to SRS and destroys SRS utility.
-// ---------------------------------------------------------
-//
-TInt CNssSpeechItemTrainer::CommitSIUpdate()
-    {
-    if ( !iSrsApi )
-        {
-        return( KErrNotReady );
-        }
-
-    iSrsApi->CommitChanges();
-
-    delete iSrsApi;
-    iSrsApi = NULL;
-
-    return( KErrNone );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::UncommitSIUpdate
-// Destroys SRS utility without committing.
-// ---------------------------------------------------------
-//
-TInt CNssSpeechItemTrainer::UncommitSIUpdate()
-    {
-    if ( !iSrsApi )
-        {
-        return( KErrNotReady );
-        }
-
-    delete iSrsApi;
-    iSrsApi = NULL;
-
-    return( KErrNone );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::SpeechItemBufferNeeded
-// Trys to allocate a speech item buffer
-// ---------------------------------------------------------
-//
-TBool CNssSpeechItemTrainer::SpeechItemBufferNeeded()
-    {
-    if ( !iSpeechItemBuffer )
-        {
-        iSpeechItemBuffer = new RPointerArray<CNssSpeechItem>;
-        if ( !iSpeechItemBuffer )
-            {
-            return( EFalse );
-            }
-        }
-
-    return( ETrue );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::SpeechItemBufferNeeded
-// Trys to allocate a grammar id buffer
-// ---------------------------------------------------------
-//
-TBool CNssSpeechItemTrainer::GrammarIdBufferNeeded()
-    {
-    if ( !iGrammarIdBuffer )
-        {
-        iGrammarIdBuffer = new RArray<TUint32>;
-        if ( !iGrammarIdBuffer )
-            {
-            return( EFalse );
-            }
-        }
-
-    return( ETrue );
-    }
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::SpeechItemBufferNeeded
-// Trys to create SRS api. Returns success status.
-// ---------------------------------------------------------
-//
-TInt CNssSpeechItemTrainer::CreateSrsApi()
-    {
-    if ( !iSrsApi )
-        {
-        TRAPD( err, iSrsApi = CNssSiUtilityWrapper::NewL( *this, KNssVASApiUid ) );
-        REACT( err, return( err ) );
-
-        iSrsApi->SetEventHandler( this );
-        }
-
-    return KErrNone;
-    }
-
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::SpeechItems2Phrases
-// Converts an array of speech items
-// into Utility's AddVoiceTags array format.
-// ---------------------------------------------------------
-//
-TInt CNssSpeechItemTrainer::SpeechItems2Phrases(
-    RPointerArray<CNssSpeechItem>& aSpeechItems,
-    RPointerArray<MDesCArray>& aPhrases )
-    {
-    // iPhraseArray is an array of arrays: 
-    // 
-    //        |-- firstname1
-    //  tag1 -|-- lastname1
-    //
-    //  tag2 -|-- firstname2
-    //        |-- lastname2
-
-    // Create training parameters, if none were given
-    if ( iTrainingParams == 0 )
-        {
-        RArray<TLanguage>* languages = new RArray<TLanguage>();
-
-        if ( !languages )
-            {
-            return( KErrNoMemory );
-            }
-
-        // Use UI language + 1 other as default if languages are not given
-        // in training parameters
-        TInt err = languages->Append( User::Language() );
-
-        if ( err == KErrNone )
-            {
-            err = languages->Append( ELangOther );
-            }
-
-        if ( err != KErrNone )
-            {
-            languages->Close();
-            delete languages;
-            return( err );
-            }
-
-        TRAP( err, iTrainingParams = CNssTrainingParameters::NewL() ); 
-        if ( err != KErrNone )
-            {
-            languages->Close();
-            delete languages;
-            return( err );
-            }
-
-        iTrainingParams->SetLanguages( languages );
-        }
-
-    // Split the phrases to subwords (names -> first name + last name)
-    for ( TInt k( 0 ); k < aSpeechItems.Count(); k++ )
-        {
-        // Split names into the first name and the last name
-        CDesC16ArrayFlat *wordArray = 0;
-
-        // Check if SINDE type of training should be used
-        TRAPD( errSinde, const RArray<RTrainingLanguageArray>& temp = 
-                                        iTrainingParams->SindeLanguagesL() );
-        if ( errSinde == KErrNone )
-            {
-            TRAP_IGNORE( wordArray = SplitPhraseSindeL( aSpeechItems[ k ]->RawText(),
-                                                        iTrainingParams->Separator() ) );
-            }
-        else
-            {
-            TRAP_IGNORE( wordArray = SplitPhraseL( aSpeechItems[ k ]->Text(),
-                                                   iTrainingParams->Separator() ) );
-            }
-
-        if ( wordArray == 0 )
-            {
-            return KErrNoMemory;
-            }
-
-        TInt ret = aPhrases.Append( wordArray );
-
-        if ( ret != KErrNone )
-            {
-            return ret;
-            }
-        }
-
-    return( KErrNone );
-    }
-    
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::SetState
-// Changes state of the trainer
-// ---------------------------------------------------------
-//
-void CNssSpeechItemTrainer::SetState(TTrainState aState) 
-	{
-	RUBY_DEBUG2("CNssSpeechItemTrainer::SetState Switching state from [%d] to [%d]", iState, aState);
-#ifdef _DEBUG
-	if( iState == EDeleteStateWaiting ) 
-		{
-		RUBY_DEBUG0("CNssSpeechItemTrainer::SetState From EDeleteStateWaiting");
-		}
-	if( aState == EDeleteStateWaiting ) 
-		{
-		RUBY_DEBUG0("CNssSpeechItemTrainer::SetState To EDeleteStateWaiting");
-		}
-		
-#endif	
-	iState = aState;
-	}
-
-// ---------------------------------------------------------
-// CNssSpeechItemTrainer::EnforceRuleIdCountInvariant
-// Adds KInvalidRuleId to the Rule ID Array, until
-// the number of rules is equal to count.
-// ---------------------------------------------------------
-//
-TInt EnforceRuleIdCountInvariant( RArray<TUint32>& aArray, TInt aCount )
-    {
-    while( aArray.Count() < aCount )
-        {
-        TInt err = aArray.Append( KInvalidRuleID );
-        if ( err != KErrNone )
-            {
-            return( err );
-            }
-        }
-
-    return KErrNone;
-    }