symhelp/helpmodel/dbwriter/DBWRITER.CPP
changeset 0 1f04cf54edd8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symhelp/helpmodel/dbwriter/DBWRITER.CPP	Tue Jan 26 15:15:23 2010 +0200
@@ -0,0 +1,630 @@
+// Copyright (c) 1999-2009 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:
+//
+
+#include "DBWRITER.H"
+#include <fbs.h>
+
+// User includes
+#include "HLPMODEL.H"
+#include "hlppanic.h"
+
+
+
+
+enum TDbWriterPanic
+	{
+	EDbWriterNoRowAtCursor,
+	EDbWriterInvalidColumnType,
+	EDbWriterStoreNotOpen
+	};
+
+
+GLDEF_C void Panic(TDbWriterPanic aReason)
+	{
+	_LIT(KHlpPanicText, "DbWriter");
+	User::Panic(KHlpPanicText, aReason);
+	}
+
+
+
+//
+// Create the database
+//
+
+CHlpRowSet::CHlpRowSet(RDbView* aView)
+		: iView(aView)
+	{
+	}
+
+EXPORT_C CHlpRowSet::~CHlpRowSet()
+	{
+	iView->Close();
+	delete iView;
+	}
+
+EXPORT_C TBool CHlpRowSet::AtRow()
+	{
+	return iView->AtRow();
+	}
+
+EXPORT_C TBool CHlpRowSet::AtBeginning()
+	{
+	return iView->AtBeginning();
+	}
+
+EXPORT_C TBool CHlpRowSet::AtEnd()
+	{
+	return iView->AtEnd();
+	}
+
+EXPORT_C TBool CHlpRowSet::FirstL()
+	{
+	return iView->FirstL();
+	}
+
+EXPORT_C TBool CHlpRowSet::LastL()
+	{
+	return iView->LastL();
+	}
+
+EXPORT_C TInt CHlpRowSet::CountL()
+	{
+	return iView->CountL();
+	}
+
+EXPORT_C void CHlpRowSet::NextL()
+	{
+	iView->NextL();
+	}
+
+EXPORT_C void CHlpRowSet::PreviousL()
+	{
+	// coverity [unchecked_value]
+	iView->PreviousL();
+	}
+
+EXPORT_C RDbView* CHlpRowSet::View()
+	{
+	return iView;
+	}
+
+
+// This method could leave while getting column set for the rowset.
+// @leave KErrNoMemory not enough memory to carry out the operation
+
+EXPORT_C TDbColNo CHlpRowSet::MapColNameToColNo(const TDesC& aName)
+	{
+	CDbColSet* columnSet = iView->ColSetL();
+	CleanupStack::PushL(columnSet);
+	TInt columnNumber = columnSet->ColNo(aName);
+	CleanupStack::PopAndDestroy(columnSet);
+	return columnNumber;
+	}
+
+
+// This method could leave while getting column set for the rowset.
+// @leave KErrNoMemory not enough memory to carry out the operation
+
+EXPORT_C TDbColNo CHlpRowSet::MapColNameToColNo(const TDbCol& aCol)
+	{
+	CDbColSet* columnSet = iView->ColSetL();
+	CleanupStack::PushL(columnSet);
+	TInt columnNumber = columnSet->ColNo(aCol.iName);
+	CleanupStack::PopAndDestroy(columnSet);
+	return columnNumber;
+	}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//
+// CHlpView class - Read only access to database views
+//
+
+CHlpView::CHlpView(RDbView* aView)
+:	CHlpRowSet(aView)
+	{
+	}
+
+CHlpView::~CHlpView()
+	{
+	View()->Close();
+	}
+
+void CHlpView::ConstructL()
+	{
+	}
+
+EXPORT_C CHlpView* CHlpView::NewLC(RDbView* aView)
+	{
+	CHlpView* self = new(ELeave)CHlpView(aView);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+EXPORT_C CHlpView* CHlpView::NewL(RDbView* aView)
+	{
+	CHlpView* self = CHlpView::NewLC(aView);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C void CHlpView::GetL()
+	{
+	View()->GetL();
+	}
+
+EXPORT_C void CHlpView::GetTextL(TDbColNo aCol, TDes& aText)
+	{
+	__ASSERT_ALWAYS(View()->AtRow(), Panic(EDbWriterNoRowAtCursor));
+	aText = View()->ColDes(aCol);
+	}
+
+EXPORT_C void CHlpView::GetRichTextL(TDbColNo aTextCol, TDbColNo aMarkupCol, CRichText& aRichText)
+	{
+	__ASSERT_ALWAYS(View()->AtRow(), Panic(EDbWriterNoRowAtCursor));
+	TPtrC ptr=View()->ColDes(aTextCol);
+	aRichText.InsertL(0, ptr);
+	GetMarkupL(aRichText, aMarkupCol);
+	}
+
+EXPORT_C void CHlpView::GetValL(TDbColNo aCol, TUint32& aValue)
+	{
+	__ASSERT_ALWAYS(View()->AtRow(), Panic(EDbWriterNoRowAtCursor));
+	aValue=View()->ColUint16(aCol);
+	}
+
+void CHlpView::GetMarkupL(CRichText& aRichText, TDbColNo aMarkupCol)
+	{
+	__ASSERT_ALWAYS(View()->ColDef(aMarkupCol).iType == EDbColLongBinary, Panic(EDbWriterInvalidColumnType));
+
+	RDbColReadStream blob;
+	blob.OpenLC(*View(), aMarkupCol);
+
+	CEmbeddedStore* embeddedStore = CEmbeddedStore::FromLC(blob);
+	RStoreReadStream markupStream;
+	markupStream.OpenLC(*embeddedStore, embeddedStore->Root());
+	aRichText.InternalizeMarkupDataL(markupStream);
+	iStoreResolver.iStore = embeddedStore;
+
+	aRichText.SetPictureFactory(iPictureFactory, &iStoreResolver);
+	aRichText.DetachFromStoreL(CPicture::EDetachFull);
+	CleanupStack::PopAndDestroy(3);	// embeddedStore, markupStream, blob
+	}
+
+
+
+
+
+
+
+
+
+
+
+//
+// CHlpTable class - write access to database views
+//
+
+CHlpTable::CHlpTable(RDbView* aView)
+:	CHlpRowSet(aView)
+	{
+	}
+
+CHlpTable::~CHlpTable()
+	{
+//	View()->Close();
+	}
+
+void CHlpTable::ConstructL()
+	{
+	}
+
+EXPORT_C CHlpTable* CHlpTable::NewLC(RDbView* aView)
+	{
+	CHlpTable* self=new(ELeave)CHlpTable(aView);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+EXPORT_C CHlpTable* CHlpTable::NewL(RDbView* aView)
+	{
+	CHlpTable* self=CHlpTable::NewLC(aView);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C void CHlpTable::InsertL()
+	{
+	View()->InsertL();
+	}
+
+EXPORT_C void CHlpTable::PutL()
+	{
+	View()->PutL();
+	}
+
+EXPORT_C void CHlpTable::SetColL(TDbColNo aCol, const TDesC& aText)
+	{
+	__ASSERT_ALWAYS(View()->AtRow(), Panic(EDbWriterNoRowAtCursor));
+	View()->SetColL(aCol, aText);
+	}
+
+EXPORT_C void CHlpTable::SetColL(TDbColNo aCol, TUint32 aValue)
+	{
+	__ASSERT_ALWAYS(View()->AtRow(), Panic(EDbWriterNoRowAtCursor));
+	View()->SetColL(aCol, aValue);
+	}
+
+EXPORT_C void CHlpTable::SetColL(TDbColNo aCol, const CFbsBitmap& aBitmap)
+	{
+	__ASSERT_ALWAYS(View()->AtRow(), Panic(EDbWriterNoRowAtCursor));
+
+	RDbColWriteStream blob;
+	blob.OpenLC(*View(), aCol);
+	blob << aBitmap;
+	blob.CommitL();
+	CleanupStack::PopAndDestroy(); // blob
+	}
+
+EXPORT_C void CHlpTable::SetColL(TDbColNo aTextCol, TDbColNo aMarkupCol, CRichText& aRichText)
+	{
+	__ASSERT_ALWAYS(View()->AtRow(), Panic(EDbWriterNoRowAtCursor));
+	HBufC* buf = HBufC::NewLC(aRichText.DocumentLength());
+	TPtr ptr = buf->Des();
+	aRichText.Extract(ptr);
+	SetLongTextL(*buf, aTextCol);
+	CleanupStack::PopAndDestroy();	// buf
+
+	if (aRichText.HasMarkupData())
+		SetMarkupL(aRichText, aMarkupCol);
+	else
+		View()->SetColNullL(aMarkupCol);
+	}
+
+EXPORT_C void CHlpTable::SetColL(TDbColNo aTextCol, CRichText& aRichText)
+	{
+	__ASSERT_ALWAYS(View()->AtRow(), Panic(EDbWriterNoRowAtCursor));
+	HBufC* buf = HBufC::NewL(aRichText.DocumentLength());
+	CleanupStack::PushL(buf);
+	TPtr ptr = buf->Des();
+	aRichText.Extract(ptr);
+	View()->SetColL(aTextCol,ptr);
+	CleanupStack::PopAndDestroy();	// buf
+	}
+
+void CHlpTable::SetLongTextL(const TDesC& aText, TDbColNo aLongTextCol)
+	{
+	RDbColWriteStream stream;
+	stream.OpenLC(*View(), aLongTextCol);
+	stream.WriteL(aText);
+	stream.CommitL();
+	CleanupStack::PopAndDestroy();	// stream
+	}
+
+void CHlpTable::SetMarkupL(CRichText& aRichText, TDbColNo aMarkupCol)
+	{
+	aRichText.DetachFromStoreL(CPicture::EDetachFull);
+	RDbColWriteStream blob;
+	blob.OpenL(*View(), aMarkupCol);
+	CEmbeddedStore* embeddedStore=CEmbeddedStore::NewLC(blob); // takes ownership of blob
+	CStoreMap* map=CStoreMap::NewLC(*embeddedStore);
+	aRichText.StoreMarkupComponentsL(*embeddedStore, *map);
+
+	RStoreWriteStream markup(*map);
+	embeddedStore->SetRootL(markup.CreateLC(*embeddedStore));
+	aRichText.ExternalizeMarkupDataL(markup);
+	markup.CommitL();
+	map->Reset();
+	CleanupStack::PopAndDestroy(2); // map, markup
+	embeddedStore->CommitL();
+	CleanupStack::PopAndDestroy(); // embeddedStore
+	}
+
+const CStreamStore& THlpStoreResolver::StreamStoreL(TInt /*aPos*/) const
+	{
+	return *iStore;
+	}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//
+// CHlpDbWriter class
+//
+
+CHlpDbWriter::CHlpDbWriter(RFs& aFs)
+:	iFs(aFs)
+	{
+	}
+
+EXPORT_C CHlpDbWriter::~CHlpDbWriter()
+	{
+	iDatabase.Close();
+	delete iTables;
+	delete iDictionary;
+	delete iStore;
+	delete iUids;
+	delete iImagesAlreadyStored;
+}
+
+void CHlpDbWriter::ConstructL()
+	{
+	iDictionary				= CStreamDictionary::NewL();
+	iTables					= new(ELeave) CArrayPtrFlat<CHlpTable>(4);
+	iUids					= new(ELeave) CArrayFixFlat<TUid>(2);
+	iImagesAlreadyStored	= new(ELeave) CArrayFixFlat<TUid>(10);
+	}
+
+EXPORT_C CHlpDbWriter* CHlpDbWriter::NewL(RFs& aFs)
+	{
+	CHlpDbWriter* self = CHlpDbWriter::NewLC(aFs);
+	CleanupStack::Pop(); //self
+	return self;
+	}
+
+EXPORT_C CHlpDbWriter* CHlpDbWriter::NewLC(RFs& aFs)
+	{
+	CHlpDbWriter* self = new(ELeave) CHlpDbWriter(aFs);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+EXPORT_C void CHlpDbWriter::SetDatabaseUidL(TUid& aUid)
+	{
+	__ASSERT_DEBUG(iStore, Panic(EDbWriterStoreNotOpen));
+
+	TUidType type(KPermanentFileStoreLayoutUid, KUidHlpApp, aUid);	
+	iStore->SetTypeL(type);
+	}
+
+EXPORT_C void CHlpDbWriter::CreateFileL(const TDesC& aFileName)
+	{
+	CPermanentFileStore* store = NULL;
+	
+	if	(!BaflUtils::FileExists(iFs, aFileName))
+		store = CPermanentFileStore::CreateL(iFs, aFileName, EFileRead|EFileWrite);
+	else // Change this so that the program panics if the file exists.
+		store = CPermanentFileStore::ReplaceL(iFs, aFileName, EFileRead|EFileWrite);
+
+	delete iStore;
+	iStore = store;
+	iFileName = aFileName;
+	}
+
+EXPORT_C void CHlpDbWriter::AddBitmapL(TInt aBitmapId)
+	{
+	TKeyArrayFix key(_FOFF(TUid, iUid), ECmpTUint);
+	iImagesAlreadyStored->InsertIsqL(TUid::Uid(aBitmapId), key);
+	}
+
+EXPORT_C TBool CHlpDbWriter::IsBitmapStored(TInt aBitmapId) const
+	{
+	TInt index = KErrNotFound;
+	TKeyArrayFix key(_FOFF(TUid, iUid), ECmpTUint);
+	return (!iImagesAlreadyStored->FindIsq(TUid::Uid(aBitmapId), key, index));
+	}
+
+EXPORT_C TInt CHlpDbWriter::BitmapCount() const
+	{
+	return iImagesAlreadyStored->Count();
+	}
+
+EXPORT_C TInt CHlpDbWriter::BitmapIdForIndex(TInt aIndex) const
+	{
+	return iImagesAlreadyStored->At(aIndex).iUid;
+	}
+
+EXPORT_C void CHlpDbWriter::CreateDatabaseL()
+	{
+	TStreamId dbStream=iDatabase.CreateL(iStore);
+	iDictionary->AssignL(KUidHlpDbStream, dbStream);
+	DoCreateDatabaseL();
+	DoOpenTablesL();
+	}
+
+void CHlpDbWriter::DoCreateDatabaseL()
+	{
+	// create the table schemas
+	User::LeaveIfError(iDatabase.Execute(KHlpDMLTopicTable));
+	User::LeaveIfError(iDatabase.Execute(KHlpDMLIndexTable));
+	User::LeaveIfError(iDatabase.Execute(KHlpDMLTopicIndexTable));
+	User::LeaveIfError(iDatabase.Execute(KHlpDMLContextTable));
+	User::LeaveIfError(iDatabase.Execute(KHlpDMLImageTable));
+
+	// create the indices
+	User::LeaveIfError(iDatabase.Execute(KHlpDMLTopicTableIdx));
+	User::LeaveIfError(iDatabase.Execute(KHlpDMLIndexTableIdx));
+	User::LeaveIfError(iDatabase.Execute(KHlpDMLTopicIndexTableIdx));
+	User::LeaveIfError(iDatabase.Execute(KHlpDMLContextTableIdx));
+	User::LeaveIfError(iDatabase.Execute(KHlpDMLImageTableIdx));
+	}
+
+EXPORT_C void CHlpDbWriter::CompressDatabaseL()
+	{
+	StoreUidsL();
+	StoreStreamDictionaryL();
+
+	iStore->CommitL();
+	iDatabase.CompressL(*iStore, iDictionary->At(KUidHlpDbStream));
+	iStore->CompactL();
+	iStore->CommitL();
+	}
+
+void CHlpDbWriter::DoOpenTablesL()
+	{
+	iTables->AppendL(DoOpenTableLC(ETopicTable));
+	CleanupStack::Pop(); // ret from DoOpenTableL
+	iTables->AppendL(DoOpenTableLC(EIndexTable));
+	CleanupStack::Pop(); // ret from DoOpenTableL
+	iTables->AppendL(DoOpenTableLC(ETopicIndexTable));
+	CleanupStack::Pop(); // ret from DoOpenTableL
+	iTables->AppendL(DoOpenTableLC(EContextTable));
+	CleanupStack::Pop(); // ret from DoOpenTableL
+	iTables->AppendL(DoOpenTableLC(EImageTable));
+	CleanupStack::Pop(); // ret from DoOpenTableL
+	}
+
+CHlpTable* CHlpDbWriter::DoOpenTableLC(TInt aTable)
+	{
+	TBuf<255> sql;
+
+	switch(aTable)
+		{
+	case ETopicTable:
+		sql=KHlpSQLTopicTable;
+		break;
+	case EIndexTable:
+		sql=KHlpSQLIndexTable;
+		break;
+	case ETopicIndexTable:
+		sql=KHlpSQLTopicIndexTable;
+		break;
+	case EContextTable:
+		sql=KHlpSQLContextTable;
+		break;
+	case EImageTable:
+		sql=KHlpSQLImageTable;
+		break;
+	default:
+		User::Leave(KErrNotSupported);
+		}
+
+	RDbView* view = new(ELeave) RDbView;
+	CleanupStack::PushL(view);
+	User::LeaveIfError(view->Prepare(iDatabase, sql, RDbView::EUpdatable));
+	User::LeaveIfError(view->EvaluateAll());
+	CHlpTable* table = CHlpTable::NewL(view);
+	CleanupStack::Pop(); // view
+	CleanupStack::PushL(table);
+
+	return table;
+	}
+
+
+
+void CHlpDbWriter::StoreUidsL()
+	{
+	RStoreWriteStream out;
+	TStreamId uidStream = out.CreateLC(*iStore);
+	iDictionary->AssignL(KUidHlpUidStream, uidStream);
+	out.WriteInt32L(iUids->Count());
+	if (iUids->Count() > 0)
+		{
+		for(TInt i=0; i < iUids->Count(); i++)
+			{
+			out.WriteInt32L((*iUids)[i].iUid);
+			}
+		}
+	out.CommitL();
+	out.Close();
+	CleanupStack::PopAndDestroy(); // out
+	}
+
+void CHlpDbWriter::StoreStreamDictionaryL()
+	{
+	// Store the stream dictionary in the root
+	RStoreWriteStream out;
+	TStreamId root = out.CreateLC(*iStore);
+	iStore->SetRootL(root);
+	out << *iDictionary;
+	out.CommitL();
+	out.Close();
+	CleanupStack::PopAndDestroy(); // out
+	}
+
+EXPORT_C void CHlpDbWriter::CloseFileL() // should this be make private and put in the destructor?
+	{
+	iDatabase.Close();
+	iStore->CompactL();
+	iStore->CommitL();
+	delete iStore;
+	iStore=NULL;
+	iUids->Reset();
+	iTables->ResetAndDestroy();
+	iTables->Reset();
+	
+	// Have to do this because there is no reset procedure for a stream dictionary
+	CStreamDictionary* newDictionary = CStreamDictionary::NewL();
+	delete iDictionary;
+	iDictionary = newDictionary;
+	}
+
+EXPORT_C void CHlpDbWriter::SetUidL(TUid aUid)
+	{
+	TKeyArrayFix key(_FOFF(TUid,iUid),ECmpTUint32);
+	TInt indexNotReferenced = KErrNotFound;
+	if	(iUids->Find(aUid,key, indexNotReferenced) != KErrNone)
+		iUids->AppendL(aUid);
+	}	
+
+EXPORT_C void CHlpDbWriter::BeginTransaction()
+	{
+	iDatabase.Begin();
+	}
+
+EXPORT_C void CHlpDbWriter::CommitTransaction()
+	{
+	iDatabase.Commit();
+	}
+
+EXPORT_C CHlpTable* CHlpDbWriter::TopicTable()
+	{
+	return iTables->At(ETopicTable);
+	}
+
+EXPORT_C CHlpTable* CHlpDbWriter::IndexTable()
+	{
+	return iTables->At(EIndexTable);
+	}
+
+EXPORT_C CHlpTable* CHlpDbWriter::TopicIndexTable()
+	{
+	return iTables->At(ETopicIndexTable);
+	}
+
+EXPORT_C CHlpTable* CHlpDbWriter::ContextTable()
+	{
+	return iTables->At(EContextTable);
+	}
+
+EXPORT_C CHlpTable* CHlpDbWriter::ImageTable()
+	{
+	return iTables->At(EImageTable);
+	}