diff -r cad71a31b7fc -r e36f3802f733 srsf/sisrscontrollerplugin/src/silexicondb.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srsf/sisrscontrollerplugin/src/silexicondb.cpp Wed Sep 01 12:29:17 2010 +0100 @@ -0,0 +1,598 @@ +/* +* 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& aMyIds ) + { + RArray 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& aLexiconIDs ) + { + // GetAllClientIDsL(KLexiconIdTable, KLexiconIdColumn, aClientUid, aLexiconIDs); + RArray ix; + ix.Reset(); + GetAllClientIDsL(KLexiconIdTable, KLexiconIdColumn, aClientUid, ix); + for(TInt i=0;i& 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 ix; + ix.Reset(); + GetAllIDsL(KLexiconIdTable, KLexiconIdColumn, ix); + for(TInt i=0;i& aPronunciationIDs ) + { + CleanupClosePushL( 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;iCount();i++) { + CSIPronunciation* aPronunciation=&(newLexicon->AtL(i)); + aPronunciationID=aPronunciation->PronunciationID(); + User::LeaveIfError(aPronunciationIDs.Append(aPronunciationID)); + } + + CleanupStack::PopAndDestroy(newLexicon); // newLexicon + // GetAllIDsL(KLexiconName, KPronunciationIDColumn, aPronunciationIDs); + CleanupStack::Pop(); + } + +// ----------------------------------------------------------------------------- +// 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 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