srsf/sisrscontrollerplugin/src/sigrammardb.cpp
branchRCL_3
changeset 19 e36f3802f733
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srsf/sisrscontrollerplugin/src/sigrammardb.cpp	Wed Sep 01 12:29:17 2010 +0100
@@ -0,0 +1,806 @@
+/*
+* Copyright (c) 2004-2007 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:  This class handles the storage and access of speaker independent
+*               grammars.  It is also responsible for allocating memory when
+*               loading grammars into the recognizer.
+*
+*/
+
+
+// INCLUDE FILES
+#include "sigrammardb.h"
+#include "rubydebug.h"
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::CSIGrammarDB
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CSIGrammarDB::CSIGrammarDB( RDbNamedDatabase& aDatabase, 
+                            RDbs& aDbSession,
+                            TInt aDrive )
+: CSICommonDB(aDatabase, aDbSession, aDrive )
+    {
+    // Nothing
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarDB::ConstructL()
+    {
+    // Nothing
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CSIGrammarDB* CSIGrammarDB::NewL( RDbNamedDatabase& aDatabase, 
+                                  RDbs& aDbSession,
+                                  TInt aDrive )
+    {
+    RUBY_DEBUG_BLOCK( "CSIGrammarDB::NewL" );
+    
+    CSIGrammarDB* self 
+        = new( ELeave ) CSIGrammarDB( aDatabase, aDbSession, aDrive );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );	
+    return self;
+    }
+  
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::~CSIGrammarDB
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CSIGrammarDB::~CSIGrammarDB()
+    {
+    RUBY_DEBUG0( "CSIGrammarDB::~CSIGrammarDB" );
+	// Delete all elements of the array before deleting the array
+	iGrammarArray.ResetAndDestroy();
+	iGrammarArray.Close();	
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::CreateGrammarL
+// Creates a new grammar  in the database.
+// -----------------------------------------------------------------------------
+//
+TSIGrammarID CSIGrammarDB::CreateGrammarL( TUid aClientUid )
+    {
+    RUBY_DEBUG_BLOCK( "CSIGrammarDB::CreateGrammarL" );
+
+    User::LeaveIfError( iDbSession.ReserveDriveSpace( iDrive, sizeof( CSIGrammar ) ) );
+	
+	TSIGrammarID grammarID = STATIC_CAST(TSIGrammarID,CreateNewIDL(KGrammarIdTable, KGrammarIdColumn, aClientUid));
+	// Construct the table name using the new grammar ID
+	TBuf<40> KGrammarName( KSIGrammarTable );
+    KGrammarName.AppendNumUC( grammarID );
+    RUBY_DEBUG1( "CSIGrammarDB::CreateGrammarL grammar ID: %i", grammarID );
+	
+	// Create a table definition
+	CDbColSet* columns = CDbColSet::NewLC();
+	
+	// add the columns  
+	// 1) Binary data, 2) binary data size
+	columns->AddL( TDbCol( KBinaryGrammarColumn, EDbColLongBinary ) );
+	columns->AddL( TDbCol( KBinaryGrammarColumnSize, EDbColUint32 ) );
+	
+	// Create a table
+	TInt err =iDb.CreateTable( KGrammarName, *columns );
+	
+	if ( err != KErrNone )
+	    {
+		// Failed to create the table.
+		// Need to release the new grammar ID and leave.
+		ReleaseIdL( KGrammarIdTable, KGrammarIdColumn, grammarID );
+		User::Leave( err );
+	    }
+
+	// Cleanup the column set
+	CleanupStack::PopAndDestroy( columns );
+	
+	// Construct the table name using the provided grammar ID
+	// Declare a literal string to hold the SQL statement
+	// SELECT KBinaryGrammarColumn , KBinaryGrammarColumn FROM  KGrammarName
+ 	_LIT(KSQLSelect1,"select  ");	
+	_LIT(KSQLSelect2," from  ");		
+	TBuf<120> KSQLStatement;		
+	KSQLStatement.Append(KSQLSelect1  );	
+	KSQLStatement.Append(KBinaryGrammarColumn );
+	KSQLStatement.Append(KNext);
+	KSQLStatement.Append(KBinaryGrammarColumnSize );	
+	KSQLStatement.Append(KSQLSelect2  );
+	KSQLStatement.Append(KGrammarName); 
+	
+	// Create a view on the database
+	RDbView view;
+	User::LeaveIfError(view.Prepare(iDb,TDbQuery(KSQLStatement,EDbCompareNormal)));
+	User::LeaveIfError(view.EvaluateAll());
+	
+	// Get the structure of rowset
+	CDbColSet* colSet = view.ColSetL(); 
+ 	// Insert a row
+	view.InsertL();
+	view.PutL();
+ 	// Close the view
+	view.Close();
+	delete colSet; 
+
+	// Put a empty grammar into the database
+	CSICompiledGrammar *aSICompiledGrammar=CSICompiledGrammar::NewL(grammarID);
+ 	CleanupStack::PushL(aSICompiledGrammar);
+	UpdateGrammarL(aClientUid,aSICompiledGrammar);
+	CleanupStack::PopAndDestroy(aSICompiledGrammar);
+
+    iDbSession.FreeReservedSpace( iDrive );
+
+ 	return grammarID;
+    } 
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::UpdateGrammarL
+// Inserts the externalized SI compiled grammar  into the specified grammar table.
+// Save the grammar into the database
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarDB::UpdateGrammarL( TUid aClientUid, 
+                                   CSICompiledGrammar *aSICompiledGrammar )
+    {
+	RUBY_DEBUG_BLOCK( "CSIGrammarDB::UpdateGrammarL" );
+
+	// verify ownership 
+	TSIGrammarID aGrammarID=aSICompiledGrammar->GrammarID();
+	VerifyOwnershipL(aClientUid, KGrammarIdTable, KGrammarIndex, aGrammarID);
+	
+	// Construct the table name using the provided grammar ID
+	// Declare a literal string to hold the SQL statement
+	// SELECT KBinaryGrammarColumn , KBinaryGrammarColumn FROM  KGrammarName
+	TBuf<40> KGrammarName(KSIGrammarTable);
+    KGrammarName.AppendNumUC(aGrammarID);	
+	_LIT(KSQLSelect1,"select  ");	
+	_LIT(KSQLSelect2," from  ");		
+	TBuf<120> KSQLStatement;		
+	KSQLStatement.Append(KSQLSelect1  );	
+	KSQLStatement.Append(KBinaryGrammarColumn );
+	KSQLStatement.Append(KNext);
+	KSQLStatement.Append(KBinaryGrammarColumnSize );	
+	KSQLStatement.Append(KSQLSelect2  );
+	KSQLStatement.Append(KGrammarName); 
+	
+	// Create a view on the database
+	RDbView view;
+	User::LeaveIfError( view.Prepare( iDb, TDbQuery( KSQLStatement,EDbCompareNormal ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+	CleanupClosePushL( view );
+	
+	// Get the structure of rowset
+	CDbColSet* colSet = view.ColSetL();
+	CleanupStack::PushL( colSet );
+	view.FirstL(); 
+	view.UpdateL();
+  
+	// Externalize a compiled grammar
+	CBufFlat* dataCopyBuffer = CBufFlat::NewL( 100 ); // 100 = expand 100 bytes
+    CleanupStack::PushL( dataCopyBuffer );              // when the buffer is full
+ 	RBufWriteStream stream;
+	stream.Open( *dataCopyBuffer );
+    CleanupClosePushL( stream );
+	aSICompiledGrammar->ExternalizeL( stream );
+	CleanupStack::PopAndDestroy( &stream );
+	
+	TPtr8 aWriteBuf( dataCopyBuffer->Ptr( 0 ) );
+	TInt BufSize = aWriteBuf.Size();
+	
+	// add binary buffer by Using the stream  
+	RDbColWriteStream out;
+	TDbColNo col = colSet->ColNo( KBinaryGrammarColumn ); // Ordinal position of long column	
+	out.OpenLC( view, col );
+	out.WriteL( aWriteBuf );	
+	out.Close();	
+	CleanupStack::PopAndDestroy(); // out
+
+	// add  size of the buffer
+	col = colSet->ColNo( KBinaryGrammarColumnSize ); // Ordinal position of  size	
+	view.SetColL( col, BufSize ); 	
+	view.PutL();
+ 
+	CleanupStack::PopAndDestroy( dataCopyBuffer );
+	CleanupStack::PopAndDestroy( colSet );
+
+	// close the view
+	CleanupStack::PopAndDestroy( &view ); // Close view
+    }
+
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::FindGrammarL
+// Find a grammar from loaded grammar array
+// -----------------------------------------------------------------------------
+CSICompiledGrammar*  CSIGrammarDB::FindGrammarL(TSIGrammarID aGrammarID) 
+    {
+    RUBY_DEBUG_BLOCK( "CSIGrammarDB::FindGrammarL" );
+    
+    TInt i(0);
+    CSICompiledGrammar* aGrammar=NULL;
+    
+    // Check if grammar already loaded
+    for ( i = 0; i < iGrammarArray.Count(); i++ )
+        {
+        if ( iGrammarArray[i]->GrammarID()==aGrammarID  )
+            { 
+            aGrammar=iGrammarArray[i];
+            break;
+            }		
+        }
+    // Can not found in the loaded grammar array
+    if(i==iGrammarArray.Count())
+        User::Leave(KErrNotFound);
+    
+    return aGrammar;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::GetNewID
+// Get a new uniq ID 
+// -----------------------------------------------------------------------------
+TInt CSIGrammarDB::GetNewID( RArray<TSIRuleID>& aMyIds )
+    {
+    RArray<TSIRuleID> myIDs = aMyIds;
+    TInt Count = myIDs.Count();
+    TInt id = 0;
+    if ( Count == 0 )
+        {
+        id = 1; // empty ,first id will be 1
+        }
+    else
+        { 
+        // Find a unique  ID
+        myIDs.SortUnsigned();
+        id = myIDs[myIDs.Count() - 1] + 1; //by default , the last one 
+        for ( TInt i = 0; i < myIDs.Count(); i++ )
+            {
+            TInt index = i + 1; 
+            TInt s = myIDs[i];
+            if ( s > index )
+                {
+                id = index;
+                break;
+                }
+            }
+        }
+    return id;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::CreateRuleL
+// Creates a new empty rule.
+// -----------------------------------------------------------------------------
+void CSIGrammarDB::CreateRuleL( TUid aClientUid, TSIGrammarID aGrammarID, 
+                                TSIRuleID& aRuleID )
+    {
+    RUBY_DEBUG_BLOCK( "CSIGrammarDB::CreateRuleL" );
+
+    //__UHEAP_MARK;
+    VerifyOwnershipL( aClientUid, KGrammarIdTable, KGrammarIndex, aGrammarID );
+    // find the grammar from the database 
+    CSICompiledGrammar* aGrammar = (CSICompiledGrammar*) GrammarL( aGrammarID );
+    CleanupStack::PushL( aGrammar );
+    
+    TInt aID = 0;
+    TInt Count=aGrammar->Count();
+    
+    // existing myRuleVariantID
+    RArray<TSIRuleID> myIDs;
+    myIDs.Reset();
+    for(TInt i = 0; i < Count; i++ )
+        {
+        CSIRule* aRule = &( aGrammar->AtL( i ) );
+        myIDs.Append( aRule->RuleID() );
+        } 
+    
+    // Find a uniq new id 
+    aID=GetNewID( myIDs );
+    myIDs.Close();
+    aRuleID=aID;
+    
+    // add the rule to the grammar	
+    CSIRule* rule = CSIRule::NewL( aRuleID );
+    CleanupStack::PushL( rule );	
+    aGrammar->AddL( rule );
+    CleanupStack::Pop( rule );
+    
+    UpdateGrammarL( aClientUid, aGrammar );
+    CleanupStack::PopAndDestroy( aGrammar );
+    //__UHEAP_MARKEND;
+    } 
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::AddRuleVariantL
+// Add Rule Variant to the array that hold the grammar array
+// -----------------------------------------------------------------------------
+void CSIGrammarDB::AddRuleVariantL(TUid aClientUid,
+								   TSIGrammarID aGrammarID, 								 
+								   TSILexiconID aLexiconID,
+								   const RArray<TSIPronunciationID>& aPronunciationIDs, 								     
+								   TSIRuleID aRuleID,
+								   TSIRuleVariantID& aRuleVariantID) 
+    {
+    VerifyOwnershipL(aClientUid, KGrammarIdTable, KGrammarIndex, aGrammarID);
+    
+    CSICompiledGrammar* aGrammar=(CSICompiledGrammar*)GrammarL(aGrammarID);
+    CleanupStack::PushL(aGrammar);
+    
+    CSIRule* aRule=&(aGrammar->RuleL(aRuleID));
+    // existing myRuleVariantID
+    RArray<TSIRuleID> myID;
+    myID.Reset();
+    for( TInt i = 0; i < aRule->Count(); i++ )
+        {
+        CSIRuleVariant* aRuleVariant=&(aRule->AtL(i));
+        myID.Append(aRuleVariant->RuleVariantID());
+        }
+    
+    // Find a uniq new id 
+    aRuleVariantID=STATIC_CAST(TSIRuleVariantID,GetNewID(myID));
+    myID.Close();	
+    
+    // add the rule variant to the rule
+    CSIRuleVariant* ruleVariant = CSIRuleVariant::NewL( aRuleVariantID, aLexiconID );
+    CleanupStack::PushL( ruleVariant );	
+    ruleVariant->SetPronunciationIDsL(aPronunciationIDs);
+    aRule->AddL( ruleVariant );
+    CleanupStack::Pop( ruleVariant );
+    UpdateGrammarL( aClientUid, aGrammar );
+    CleanupStack::PopAndDestroy( aGrammar );	  
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::LoadGrammarL
+// Loads all rules within the specified grammar into a grammar object, which
+// is loaded into recognizer during recognition session.
+// Note : Will leave if already loaded
+// -----------------------------------------------------------------------------
+//
+const CSICompiledGrammar* CSIGrammarDB::LoadGrammarL( TSIGrammarID aGrammarID )
+    {
+    // Construct the table name using the provided grammar ID
+    // Construct the table name using the provided grammar ID
+    // Declare a literal string to hold the SQL statement
+    // SELECT KBinaryGrammarColumn , KBinaryGrammarColumn FROM  KGrammarName
+    TBuf<40> KGrammarName(KSIGrammarTable);
+    KGrammarName.AppendNumUC(aGrammarID);
+    
+    // Create newGrammar object	
+    CSICompiledGrammar* grammar = CSICompiledGrammar::NewLC( aGrammarID );	
+    _LIT(KSQLSelect1,"select  ");	
+    _LIT(KSQLSelect2," from  ");
+    TBuf<120> KSQLStatement;		
+    KSQLStatement.Append(KSQLSelect1  );		
+    KSQLStatement.Append(KBinaryGrammarColumn );
+    KSQLStatement.Append(KNext);
+    KSQLStatement.Append(KBinaryGrammarColumnSize );
+    KSQLStatement.Append(KSQLSelect2  );
+    KSQLStatement.Append(KGrammarName); 
+    
+    // create a view on the database
+    RDbView view;
+    CleanupClosePushL( view );
+    
+    User::LeaveIfError(view.Prepare(iDb,TDbQuery(KSQLStatement,EDbCompareNormal)));
+    User::LeaveIfError(view.EvaluateAll());
+    
+    // Get the structure of the rowset 
+    CDbColSet* colSet = view.ColSetL();
+    CleanupStack::PushL( colSet );
+    
+    // iterate across the row set, one row only
+    for (view.FirstL();view.AtRow();view.NextL())
+        {
+        
+        // retrieve the row
+        view.GetL();		
+        
+        // first retrieve the size of binary package 
+        TDbColNo col = colSet->ColNo(KBinaryGrammarColumnSize); // Ordinal position of long column 
+        TInt32 size = view.ColUint32( col);
+        
+        TUint8* buf = new (ELeave) TUint8[size];		
+        CleanupStack::PushL( buf);			
+        TPtr8 readBuf( buf, size, size);
+        CBufFlat* dataCopyBuffer = CBufFlat::NewL( 100 ); // 100 = expand 100 bytes
+        CleanupStack::PushL(dataCopyBuffer);              // when the buffer is full
+        
+        RBufReadStream stream;
+        CleanupClosePushL( stream );
+        stream.Open(*dataCopyBuffer);
+        
+        // and a stream for long columns
+        RDbColReadStream in;
+        CleanupClosePushL( in );
+        col = colSet->ColNo(KBinaryGrammarColumn); // Ordinal position of long column 
+        
+        
+        in.OpenLC(view, col);
+        in.ReadL( readBuf, view.ColLength(col));
+        dataCopyBuffer->InsertL(0,readBuf);
+        grammar->InternalizeL( stream );
+        
+        CleanupStack::PopAndDestroy( col );
+        CleanupStack::PopAndDestroy( &in );
+        CleanupStack::PopAndDestroy( &stream ); 
+        CleanupStack::PopAndDestroy( dataCopyBuffer );
+        CleanupStack::PopAndDestroy( buf );
+        } 
+        
+    CleanupStack::PopAndDestroy( colSet );
+    CleanupStack::PopAndDestroy( &view );
+    
+    // Keep the reference of the grammar object
+    User::LeaveIfError(iGrammarArray.Append(grammar));
+    // Cleanup grammar
+    CleanupStack::Pop(grammar );
+    return grammar;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::GrammarL
+// Loads all rules within the specified grammar into a grammar object, which
+// is loaded into recognizer during recognition session.
+// Note : Will leave if already loaded
+// -----------------------------------------------------------------------------
+//
+const CSICompiledGrammar* CSIGrammarDB::GrammarL( TSIGrammarID aGrammarID )
+    {
+ 	  
+    // Construct the table name using the provided grammar ID
+    // Construct the table name using the provided grammar ID
+    // Declare a literal string to hold the SQL statement
+    // SELECT KBinaryGrammarColumn , KBinaryGrammarColumn FROM  KGrammarName
+    TBuf<40> KGrammarName(KSIGrammarTable);
+    KGrammarName.AppendNumUC(aGrammarID);
+    // Create newGrammar object	 
+    CSICompiledGrammar* aGrammar = CSICompiledGrammar::NewLC( aGrammarID );
+    _LIT(KSQLSelect1,"select  ");
+    _LIT(KSQLSelect2," from  ");
+    
+    TBuf<120> KSQLStatement;		
+    KSQLStatement.Append(KSQLSelect1  );		
+    KSQLStatement.Append(KBinaryGrammarColumn );
+    KSQLStatement.Append(KNext);
+    KSQLStatement.Append(KBinaryGrammarColumnSize );
+    KSQLStatement.Append(KSQLSelect2  );
+    KSQLStatement.Append(KGrammarName); 
+    
+    // create a view on the database
+    RDbView view;
+    User::LeaveIfError(view.Prepare(iDb,TDbQuery(KSQLStatement,EDbCompareNormal)));
+    
+    User::LeaveIfError(view.EvaluateAll());
+    
+    // Get the structure of the rowset 
+    CDbColSet* colSet = view.ColSetL();
+    
+    // iterate across the row set, one row only
+    for (view.FirstL();view.AtRow();view.NextL())
+        {
+        
+        // retrieve the row
+        view.GetL();
+        
+        // first retrieve the size of binary package 
+        TDbColNo col = colSet->ColNo(KBinaryGrammarColumnSize); // Ordinal position of long column 
+        TInt32 Size = view.ColUint32( col);
+        
+        TUint8* aBuf = new (ELeave) TUint8[Size];		
+        CleanupStack::PushL(aBuf);			
+        TPtr8 aReadBuf(aBuf, Size, Size);
+        CBufFlat* dataCopyBuffer = CBufFlat::NewL( 100 ); // 100 = expand 100 bytes
+        CleanupStack::PushL(dataCopyBuffer);              // when the buffer is full
+        
+        RBufReadStream stream;
+        stream.Open(*dataCopyBuffer);
+        
+        // and a stream for long columns
+        RDbColReadStream in;
+        col = colSet->ColNo(KBinaryGrammarColumn); // Ordinal position of long column 
+        
+        
+        in.OpenLC(view, col);
+        in.ReadL(aReadBuf, view.ColLength(col));
+        dataCopyBuffer->InsertL(0,aReadBuf);
+        aGrammar->InternalizeL( stream );
+        
+        in.Close(); 		
+        CleanupStack::PopAndDestroy(3); // in dataCopyBuffer aBuf
+        }
+    //! clean the memory
+    delete colSet;
+    view.Close();  
+    
+    // Keep the reference of the grammar object
+    // Cleanup grammar
+    CleanupStack::Pop( aGrammar );
+    
+    return aGrammar;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::CreateIDTableL
+// Creates a new grammar ID table in the database.
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarDB::CreateIDTableL()
+    {
+    // Invoke function in the base class CSICommonDB.
+    CSICommonDB::CreateIDTableL(KGrammarIdTable, KGrammarIdColumn, KGrammarIndex);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::GetAllClientGrammarIDsL
+// This function returns all grammar IDs owned by the specified client.
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarDB::GetAllClientGrammarIDsL( TUid aClientUid,
+                                            RArray<TSIGrammarID>& aGrammarIDs )
+    {
+    RArray<TUint32> ix; 
+    ix.Reset();	
+    GetAllClientIDsL(KGrammarIdTable, KGrammarIdColumn, aClientUid, ix);
+    for(TInt i=0;i<ix.Count();i++) {
+        aGrammarIDs.Append(STATIC_CAST(TSIGrammarID,ix[i]));
+        }
+    ix.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::GetAllGrammarIDsL
+// This function returns all grammar IDs in the database.
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarDB::GetAllGrammarIDsL( RArray<TSIGrammarID>& aGrammarIDs )
+    {
+    // This is a hack to get the id aligned to 4-byte boundary,
+    // for some reason this does not happen in winscw build if 
+    // TSIGrammarID is taken from stack.
+    TSIGrammarID* id = new (ELeave) TSIGrammarID;
+    
+    CleanupStack::PushL( id );
+    
+    RArray<TUint32> ix;
+    //! Reset
+    ix.Reset(); 
+    GetAllIDsL(KGrammarIdTable, KGrammarIdColumn,  ix);
+    for(TInt i=0;i<ix.Count();i++) 
+        {
+        *id = STATIC_CAST( TSIGrammarID, ix[i] );
+        aGrammarIDs.Append( *id );
+        }
+    ix.Close();
+    CleanupStack::PopAndDestroy( id );
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::GetAllRuleIDsL
+// This function returns all rule IDs within the specified grammar.
+// grammar have to be loaded 
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarDB::GetAllRuleIDsL( TSIGrammarID aGrammarID,
+                                   RArray<TSIRuleID>& aRuleIDs )
+    {
+	CleanupClosePushL( aRuleIDs );
+	
+    // Construct the table name using the provided grammar ID
+    TBuf<40> KGrammarName(KSIGrammarTable);
+    KGrammarName.AppendNumUC(aGrammarID);
+    
+    CSICompiledGrammar* newgrammar =( CSICompiledGrammar* )GrammarL( aGrammarID) ;// Load the grammar from database	
+    CleanupStack::PushL(newgrammar);
+    TSIRuleID	RuleId;
+    
+    for (TInt  i=0;i<newgrammar->Count();i++) {
+        CSIRule* aRule=&(newgrammar->AtL(i));
+        RuleId=aRule->RuleID();		
+        User::LeaveIfError(aRuleIDs.Append(RuleId));
+        } 
+    CleanupStack::PopAndDestroy(newgrammar);
+    CleanupStack::Pop();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::RemoveGrammarL
+// Deletes a grammar table from the database.
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarDB::RemoveGrammarL( TUid aClientUid,
+                                   TSIGrammarID aGrammarID )
+    {
+    VerifyOwnershipL(aClientUid, KGrammarIdTable, KGrammarIndex, aGrammarID);
+    
+    TInt diskSpace = ( RuleCountL(aGrammarID) * sizeof( CSIRule) ) 
+        + sizeof( CSIGrammar );
+    User::LeaveIfError( iDbSession.ReserveDriveSpace( iDrive, diskSpace ) );
+    
+    // Construct the table name using the provided grammar ID
+    TBuf<40> KGrammarName(KSIGrammarTable);
+    KGrammarName.AppendNumUC(aGrammarID);
+    
+    TBuf<50> KSQLStatement;
+    // Declare a literal string to hold the SQL statement
+    // DROP TABLE KGrammarName
+    _LIT(KSQLDelete1, "DROP TABLE ");
+    
+    KSQLStatement = KSQLDelete1;
+    KSQLStatement.Append(KGrammarName);
+    
+    User::LeaveIfError(iDb.Execute(KSQLStatement));
+    
+    // Release the grammar ID
+    ReleaseIdL(KGrammarIdTable, KGrammarIdColumn, aGrammarID);
+    
+    // Cancel free disk space request
+    iDbSession.FreeReservedSpace( iDrive );
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::RuleCountL
+// Returns the number of rules in the specified grammar.
+// Grammar have to be loaded
+// -----------------------------------------------------------------------------
+//
+TInt CSIGrammarDB::RuleCountL( TSIGrammarID aGrammarID )
+    {
+    // Load a grammar
+    CSICompiledGrammar* aGrammar=(CSICompiledGrammar*)GrammarL(aGrammarID);
+    CleanupStack::PushL(aGrammar);  
+    // Count the number of the rules inside the grammar
+    TInt RuleCount=aGrammar->Count();	 
+    CleanupStack::PopAndDestroy(aGrammar);
+    return RuleCount;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::RemoveRuleL
+// Deletes Rule from the database.
+// Grammar have to be loaded
+// -----------------------------------------------------------------------------
+//  
+void CSIGrammarDB::RemoveRuleL( TUid aClientUid, 
+                                TSIGrammarID aGrammarID,
+                                TSIRuleID aRuleID )
+    {
+    VerifyOwnershipL(aClientUid, KGrammarIdTable, KGrammarIndex, aGrammarID);
+    CSICompiledGrammar* aGrammar=(CSICompiledGrammar*)GrammarL(aGrammarID);	 
+    
+    CleanupStack::PushL(aGrammar);  
+    if (aGrammar->Find(aRuleID)==KErrNotFound)
+        {
+        User::Leave(KErrNotFound);
+        }
+    else
+        {
+        aGrammar->DeleteL(aRuleID);
+        }
+    UpdateGrammarL(aClientUid,aGrammar);
+    CleanupStack::PopAndDestroy(aGrammar);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::IsGrammarLoaded
+// Checks to see if a valid grammar is loaded into the recognizer.  This is
+// useful to check if any rules are still loaded after performing UnloadRule().
+// -----------------------------------------------------------------------------
+//
+TBool CSIGrammarDB::IsGrammarLoaded()
+    {
+    for ( TInt i = 0; i < iGrammarArray.Count(); i++ )
+        {
+        if ( iGrammarArray[i]->Count() > 0 )
+            {
+            // As long as there is still a rule.
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::IsRuleValidL
+// Checks if the rule is valid or not.
+// -----------------------------------------------------------------------------
+//
+TBool CSIGrammarDB::IsRuleValidL( TSIGrammarID aGrammarID, TSIRuleID aRuleID )
+    {
+    CSICompiledGrammar* aGrammar=(CSICompiledGrammar*)GrammarL(aGrammarID);
+    CleanupStack::PushL(aGrammar);  
+    if (aGrammar->Find(aRuleID)==KErrNotFound)
+        {
+        CleanupStack::PopAndDestroy(aGrammar);
+        return EFalse; 
+        }
+    else {
+        CleanupStack::PopAndDestroy(aGrammar);
+        return ETrue;	
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::ResetAndDestroy
+// Deallocates the temporary memory containing the grammar object created with
+// AllRulesL.
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarDB::ResetAndDestroy()
+    {
+    iGrammarArray.ResetAndDestroy();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::UnloadRule
+// Unloads the specified rule from the specified grammar in temporary memory,
+// previously loaded with AllRulesL.  The rule in the database remains intact.
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarDB::UnloadRuleL( TSIGrammarID aGrammarID,
+                                TSIRuleID aRuleID )
+    {
+    CSIGrammar* grammar;
+    
+    for( TInt i = 0; i < iGrammarArray.Count(); i++ )
+        {
+        grammar = iGrammarArray[i];
+        if ( grammar->GrammarID() == aGrammarID )
+            {
+            grammar->DeleteL(aRuleID);
+            return;
+            }
+        }
+    User::Leave(KErrNotFound);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::UnloadGrammar
+// Unloads  the specified grammar in temporary memory,
+// previously loaded with AllRulesL.  The grammar in the database remains intact.
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarDB::UnloadGrammarL( TSIGrammarID aGrammarID)
+    {
+    CSIGrammar* grammar;
+    
+    for( TInt i = 0; i < iGrammarArray.Count(); i++ )
+        {
+        grammar = iGrammarArray[i];
+        if ( grammar->GrammarID() == aGrammarID )
+            {
+            //! delete the object 
+            delete iGrammarArray[i];
+            // remove the pointer
+            iGrammarArray.Remove(i);
+            return;
+            }
+        }
+    User::Leave(KErrNotFound);
+    }
+
+//  End of File