--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/srsf/sisrscontrollerplugin/src/silexicondb.cpp Thu Dec 17 08:46:30 2009 +0200
@@ -0,0 +1,595 @@
+/*
+* 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
+* lexicons. It is also responsible for allocating memory when
+* loading lexicons into the recognizer.
+*
+*/
+
+
+// INCLUDE FILES
+#include "silexicondb.h"
+#include "rubydebug.h"
+
+// CONSTANTS
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::CSILexiconDB
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CSILexiconDB::CSILexiconDB( RDbNamedDatabase& aDatabase,
+ RDbs& aDbSession,
+ TInt aDrive )
+: CSICommonDB(aDatabase, aDbSession, aDrive )
+{
+}
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CSILexiconDB::ConstructL()
+ {
+ RUBY_DEBUG_BLOCK( "CSILexiconDB::ConstructL" );
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CSILexiconDB* CSILexiconDB::NewL( RDbNamedDatabase& aDatabase,
+ RDbs& aDbSession,
+ TInt aDrive )
+ {
+ RUBY_DEBUG_BLOCK( "CSILexiconDB::NewL" );
+ CSILexiconDB* self
+ = new( ELeave ) CSILexiconDB( aDatabase, aDbSession, aDrive );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::~CSILexiconDB
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CSILexiconDB::~CSILexiconDB()
+ {
+ // Delete all elements of the array before deleting the array
+ // iLexiconArray.ResetAndDestroy();
+ // iLexiconArray.Close();
+ RUBY_DEBUG0( "CSILexiconDB::~CSILexiconDB" );
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::CreateLexiconL
+// Creates a new lexicon table in the database.
+// -----------------------------------------------------------------------------
+//
+TSILexiconID CSILexiconDB::CreateLexiconL( TUid aClientUid )
+ {
+ RUBY_DEBUG_BLOCK( "CSILexiconDB::CreateLexiconL" );
+
+ User::LeaveIfError( iDbSession.ReserveDriveSpace( iDrive, sizeof( CSILexicon ) ) );
+
+ // Generate a new Lexicon ID
+ TSILexiconID lexiconID = STATIC_CAST(TSILexiconID,CreateNewIDL(KLexiconIdTable, KLexiconIdColumn, aClientUid ));
+
+ // Construct the table name using the new lexicon ID
+ TBuf<40> KLexiconName( KSILexiconTable );
+ KLexiconName.AppendNumUC( lexiconID );
+ RUBY_DEBUG1( "CSILexiconDB::CreateLexiconL lexicon ID: %i", lexiconID );
+
+
+ // Create a table definition
+ CDbColSet* columns = CDbColSet::NewLC();
+
+ // add the columns
+ // 1) Binary data, 2) binary data size
+ columns->AddL( TDbCol( KBinaryLexiconColumn, EDbColLongBinary ) );
+ columns->AddL( TDbCol( KBinaryLexiconColumnSize, EDbColUint32 ) );
+
+ // Create a table
+ TInt err =iDb.CreateTable( KLexiconName, *columns );
+
+ if ( err != KErrNone )
+ {
+ // Failed to create the table.
+ // Need to release the new Lexicon ID and leave.
+ ReleaseIdL( KLexiconIdTable, KLexiconIdColumn, lexiconID );
+ 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 KBinaryLexiconColumn , KBinaryLexiconColumn FROM KLexiconName
+ _LIT(KSQLSelect1,"select ");
+ _LIT(KSQLSelect2," from ");
+ TBuf<120> KSQLStatement;
+ KSQLStatement.Append(KSQLSelect1 );
+ KSQLStatement.Append(KBinaryLexiconColumn );
+ KSQLStatement.Append(KNext);
+ KSQLStatement.Append(KBinaryLexiconColumnSize );
+ KSQLStatement.Append(KSQLSelect2 );
+ KSQLStatement.Append(KLexiconName);
+
+ // 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();
+ view.InsertL();
+ view.PutL();
+
+
+ // close the view
+ view.Close();
+ delete colSet;
+
+ // add an empty lexicon
+ CSILexicon *aLexicon=CSILexicon::NewL(lexiconID);
+ CleanupStack::PushL(aLexicon);
+ UpdateLexiconL(aClientUid,aLexicon);
+ CleanupStack::PopAndDestroy(aLexicon);
+
+ iDbSession.FreeReservedSpace( iDrive );
+
+ return lexiconID;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::UpdateLexiconL
+// Inserts the externalized SI Lexicon into the specified grammar table.
+// Save the Lexicon into the database
+// -----------------------------------------------------------------------------
+//
+void CSILexiconDB::UpdateLexiconL( TUid aClientUid,
+ CSILexicon *aSILexicon )
+ {
+
+ // __UHEAP_MARK;
+ TSILexiconID aLexiconID=aSILexicon->LexiconID();
+ VerifyOwnershipL(aClientUid, KLexiconIdTable, KLexiconIndex, aLexiconID);
+
+ // Construct the table name using the provided grammar ID
+ // Declare a literal string to hold the SQL statement
+ // SELECT KBinaryLexiconColumn , KBinaryLexiconColumn FROM KLexiconName
+ TBuf<40> KLexiconName(KSILexiconTable);
+ KLexiconName.AppendNumUC(aLexiconID);
+ _LIT(KSQLSelect1,"select ");
+ _LIT(KSQLSelect2," from ");
+ TBuf<120> KSQLStatement;
+ KSQLStatement.Append(KSQLSelect1 );
+ KSQLStatement.Append(KBinaryLexiconColumn );
+ KSQLStatement.Append(KNext);
+ KSQLStatement.Append(KBinaryLexiconColumnSize );
+ KSQLStatement.Append(KSQLSelect2 );
+ KSQLStatement.Append(KLexiconName);
+
+ // 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();
+
+ view.FirstL();
+ view.UpdateL();
+
+
+ // Externalize grammar
+ CBufFlat* dataCopyBuffer = CBufFlat::NewL( 100 ); // 100 = expand 100 bytes
+ CleanupStack::PushL(dataCopyBuffer); // when the buffer is full
+ //TPtr8 Buft((TUint8*) abuf,3,3);
+ //dataCopyBuffer->InsertL(0,Buft);
+ RBufWriteStream stream;
+ stream.Open(*dataCopyBuffer);
+ CleanupClosePushL(stream);
+ aSILexicon->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(KBinaryLexiconColumn); // 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(KBinaryLexiconColumnSize); // Ordinal position of size
+ view.SetColL( col,BufSize);
+
+ view.PutL();
+
+ // close the view
+ view.Close();
+
+
+ delete colSet;
+ CleanupStack::PopAndDestroy( dataCopyBuffer );
+ // __UHEAP_MARKEND;
+ }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarDB::GetNewID
+// Get a new uniq ID
+// -----------------------------------------------------------------------------
+TInt CSILexiconDB::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 Rulevariant 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;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::CreateIDTableL
+// Creates a new lexicon ID table in the database.
+// -----------------------------------------------------------------------------
+//
+void CSILexiconDB::CreateIDTableL()
+ {
+ // Invoke function in the base class CSICommonDB.
+ CSICommonDB::CreateIDTableL(KLexiconIdTable, KLexiconIdColumn, KLexiconIndex);
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::GetAllClientLexiconIDsL
+// This function returns all Lexicon IDs owned by the specified client.
+// -----------------------------------------------------------------------------
+//
+void CSILexiconDB::GetAllClientLexiconIDsL( TUid aClientUid,
+ RArray<TSILexiconID>& aLexiconIDs )
+ {
+ // GetAllClientIDsL(KLexiconIdTable, KLexiconIdColumn, aClientUid, aLexiconIDs);
+ RArray<TUint32> ix;
+ ix.Reset();
+ GetAllClientIDsL(KLexiconIdTable, KLexiconIdColumn, aClientUid, ix);
+ for(TInt i=0;i<ix.Count();i++)
+ aLexiconIDs.Append(STATIC_CAST(TSILexiconID,ix[i]));
+ ix.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::GetAllLexiconIDsL
+// This function returns all Lexicon IDs in the database.
+// -----------------------------------------------------------------------------
+//
+void CSILexiconDB::GetAllLexiconIDsL( RArray<TSILexiconID>& aLexiconIDs )
+ {
+ // This is a hack to get the id aligned to 4-byte boundary,
+ // for some reason this does not happen in winscw build if
+ // TSILexiconID is taken from stack.
+ TSILexiconID* id = new (ELeave) TSILexiconID;
+ CleanupStack::PushL( id );
+
+ // GetAllIDsL(KLexiconIdTable, KLexiconIdColumn, aLexiconIDs);
+ RArray<TUint32> ix;
+ ix.Reset();
+ GetAllIDsL(KLexiconIdTable, KLexiconIdColumn, ix);
+ for(TInt i=0;i<ix.Count();i++)
+ {
+ *id = STATIC_CAST( TSILexiconID, ix[i] );
+ aLexiconIDs.Append( *id );
+ }
+ ix.Close();
+ CleanupStack::PopAndDestroy( id );
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::GetAllPronunciationIDsL
+// This function returns all Pronunciation IDs within the specified Lexicon.
+// Lexicon have to be loaded
+// -----------------------------------------------------------------------------
+//
+void CSILexiconDB::GetAllPronunciationIDsL( TSILexiconID aLexiconID, RArray<TSIPronunciationID>& aPronunciationIDs )
+ {
+ // Construct the table name using the provided Lexicon ID
+ TBuf<40> KLexiconName(KSILexiconTable);
+ KLexiconName.AppendNumUC(aLexiconID);
+
+ CSILexicon* newLexicon = LexiconL( aLexiconID) ;// Load the Lexicon from database
+ CleanupStack::PushL(newLexicon);
+
+ TSIPronunciationID aPronunciationID;
+ for (TInt i=0;i<newLexicon->Count();i++) {
+ CSIPronunciation* aPronunciation=&(newLexicon->AtL(i));
+ aPronunciationID=aPronunciation->PronunciationID();
+ User::LeaveIfError(aPronunciationIDs.Append(aPronunciationID));
+ }
+
+ CleanupStack::PopAndDestroy(newLexicon); // newLexicon
+ // GetAllIDsL(KLexiconName, KPronunciationIDColumn, aPronunciationIDs);
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::RemoveLexiconL
+// Deletes a Lexicon table from the database.
+// -----------------------------------------------------------------------------
+//
+void CSILexiconDB::RemoveLexiconL( TUid aClientUid,
+ TSILexiconID aLexiconID )
+ {
+
+ VerifyOwnershipL(aClientUid, KLexiconIdTable, KLexiconIndex, aLexiconID);
+
+
+ /* Some times removing of corrupted lexicon fails because of this:
+ TInt diskSpace = ( PronunciationCountL(aLexiconID) * sizeof( CSIPronunciation ) )
+ + sizeof( CSILexicon );
+ User::LeaveIfError( iDbSession.ReserveDriveSpace( iDrive, diskSpace ) );
+ */
+
+ // Construct the table name using the provided Lexicon ID
+ TBuf<40> KLexiconName(KSILexiconTable);
+ KLexiconName.AppendNumUC(aLexiconID);
+
+ TBuf<50> KSQLStatement;
+ // Declare a literal string to hold the SQL statement
+ // DROP TABLE KLexiconName
+ _LIT(KSQLDelete1, "DROP TABLE ");
+
+ KSQLStatement = KSQLDelete1;
+ KSQLStatement.Append(KLexiconName);
+
+ User::LeaveIfError(iDb.Execute(KSQLStatement));
+
+ // Release the Lexicon ID
+ ReleaseIdL(KLexiconIdTable, KLexiconIdColumn, aLexiconID);
+
+ // Cancel free disk space request
+ //iDbSession.FreeReservedSpace( iDrive );
+
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::PronunciationCountL
+// Returns the number of Pronunciations in the specified Lexicon.
+// -----------------------------------------------------------------------------
+TInt CSILexiconDB::PronunciationCountL( TSILexiconID aLexiconID )
+ {
+
+ CSILexicon* newLexicon = LexiconL( aLexiconID) ;
+ CleanupStack::PushL(newLexicon);
+
+ TInt PronunciationCount=newLexicon->Count();
+ CleanupStack::PopAndDestroy(newLexicon);
+ return PronunciationCount;
+
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::IsPronunciationValidL
+// Checks if the specified pronunciation exists in the specified loaded .
+//
+// -----------------------------------------------------------------------------
+//
+TBool CSILexiconDB::IsPronunciationValidL( TSILexiconID aLexiconID,
+ TSIPronunciationID aPronunciationID )
+ {
+ CSILexicon* newLexicon = LexiconL( aLexiconID) ;
+ CleanupStack::PushL(newLexicon);
+
+ if (newLexicon->Find(aPronunciationID)==KErrNotFound) {
+ CleanupStack::PopAndDestroy(newLexicon); // newLexicon
+ return EFalse;
+ }
+ else {
+ CleanupStack::PopAndDestroy(newLexicon); // newLexicon
+ return ETrue;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::ResetAndDestroy
+// Deallocates the temporary memory containing the Lexicon object created with
+// AllPronunciationsL.
+// -----------------------------------------------------------------------------
+//
+void CSILexiconDB::ResetAndDestroy()
+ {
+ // iLexiconArray.ResetAndDestroy();
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::RemovePronunciationL
+// Deletes Pronunciation from the database.
+// -----------------------------------------------------------------------------
+//
+void CSILexiconDB::RemovePronunciationL( TUid aClientUid,
+ TSILexiconID aLexiconID,
+ TSIPronunciationID aPronunciationID
+ )
+ {
+ // Check the ownership first
+ VerifyOwnershipL(aClientUid, KLexiconIdTable, KLexiconIndex, aLexiconID);
+
+ CSILexicon* newLexicon = LexiconL( aLexiconID);
+ CleanupStack::PushL(newLexicon);
+
+ if (newLexicon->Find(aPronunciationID)==KErrNotFound)
+ User::Leave(KErrNotFound);
+ else
+ newLexicon->DeleteL(aPronunciationID);
+ UpdateLexiconL(aClientUid , newLexicon);
+ CleanupStack::PopAndDestroy(newLexicon); // newLexicon
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::AddPronunciationL
+// Add Pronunciation to the database.
+// -----------------------------------------------------------------------------
+//
+TSIPronunciationID CSILexiconDB::AddPronunciationL( TUid aClientUid,
+ TSILexiconID aLexiconID,
+ TDesC8& aPronunciationPr,
+ TSIModelBankID aModelBankID)
+ {
+ // Check the ownership first
+ VerifyOwnershipL( aClientUid, KLexiconIdTable, KLexiconIndex, aLexiconID );
+
+ CSILexicon* aLexicon = LexiconL( aLexiconID );
+ CleanupStack::PushL( aLexicon );
+
+ // existing myPronunciationID
+ RArray<TSIPronunciationID> myPronunciationID;
+ myPronunciationID.Reset();
+ for( TInt i = 0; i < aLexicon->Count(); i++ )
+ {
+ CSIPronunciation* aPronunciation = &( aLexicon->AtL( i ) );
+ myPronunciationID.Append( aPronunciation->PronunciationID() );
+ }
+
+ // Find a uniq new id
+ TSIPronunciationID aPronunciationID = GetNewID( myPronunciationID );
+ myPronunciationID.Close();
+
+ // add the phoneme sequence to the Pronunciation
+ CSIPronunciation* pronunciation = CSIPronunciation::NewL( aPronunciationID, aModelBankID );
+ CleanupStack::PushL( pronunciation );
+ pronunciation->SetPhonemeSequenceL( aPronunciationPr );
+ aLexicon->AddL( pronunciation );
+ CleanupStack::Pop( pronunciation ); // aPronunciation
+ UpdateLexiconL( aClientUid,aLexicon );
+ CleanupStack::PopAndDestroy( aLexicon ); // aLexicon
+ return aPronunciationID;
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconDB::LexiconL
+// Loads all pronunciations within the specified lexicon into a lexicon object
+// -----------------------------------------------------------------------------
+//
+CSILexicon* CSILexiconDB::LexiconL( TSILexiconID aLexiconID )
+ {
+
+ // 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 KBinaryLexiconColumn , KBinaryLexiconColumn FROM KLexiconName
+ TBuf<40> KLexiconName(KSILexiconTable);
+ KLexiconName.AppendNumUC(aLexiconID);
+ // Create newLexicon object
+ CSILexicon* lexicon = CSILexicon::NewLC( aLexiconID );
+ _LIT(KSQLSelect1,"select ");
+ _LIT(KSQLSelect2," from ");
+ TBuf<120> KSQLStatement;
+ KSQLStatement.Append(KSQLSelect1 );
+ KSQLStatement.Append(KBinaryLexiconColumn );
+ KSQLStatement.Append(KNext);
+ KSQLStatement.Append(KBinaryLexiconColumnSize );
+ KSQLStatement.Append(KSQLSelect2 );
+ KSQLStatement.Append(KLexiconName);
+
+ // 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(KBinaryLexiconColumnSize); // 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(KBinaryLexiconColumn); // Ordinal position of long column
+
+
+ in.OpenLC(view, col);
+ in.ReadL(readBuf, view.ColLength(col));
+ dataCopyBuffer->InsertL(0,readBuf);
+ lexicon->InternalizeL( stream );
+
+ CleanupStack::PopAndDestroy( col );
+ CleanupStack::PopAndDestroy( &in );
+ CleanupStack::PopAndDestroy( &stream );
+ CleanupStack::PopAndDestroy( dataCopyBuffer );
+ CleanupStack::PopAndDestroy( buf );
+ }
+
+ CleanupStack::PopAndDestroy( colSet );
+ CleanupStack::PopAndDestroy( &view );
+
+
+
+ // Cleanup lexicon
+ CleanupStack::Pop( lexicon );
+ return lexicon;
+ }
+
+// End of File