examples/ForumNokia/DBMS/src/DBMSEngine.cpp

00001 /*
00002  * Copyright  2008 Nokia Corporation.
00003  */
00004 
00005 #include     // CDesCArrayFlat
00006 #include     // CFileStore & CPermanentFileStore
00007 #include     // file helpers
00008 #include 
00009 #include "DBMSEngine.h"
00010 
00011 // Implementation specific constants
00012 const int KCustomSqlMaxLength = 256;
00013 const int KArrayGranularity = 5;     // for CDesCArrayFlat
00014 
00015 // ---------------------------------------------------------------------------
00016 // CBookDb::NewL()
00017 //
00018 // Create instance of the Book database engine.
00019 // ---------------------------------------------------------------------------
00020 CBookDb* CBookDb::NewL() 
00021     {
00022     CBookDb* tmp = new (ELeave)CBookDb();
00023     CleanupStack::PushL(tmp);
00024     tmp->ConstructL();
00025     CleanupStack::Pop();
00026     return tmp;
00027     }
00028 
00029 // ---------------------------------------------------------------------------
00030 // CBookDb::~CBookDb()
00031 //
00032 // Destructor of the Book database engine. Release resources.
00033 // ---------------------------------------------------------------------------
00034 CBookDb::~CBookDb()
00035     {
00036     Close();  // Just in case, if the user does not close this explicitely
00037     iFsSession.Close();
00038     }
00039 
00040 // ---------------------------------------------------------------------------
00041 // CBookDb::ConstructL()
00042 //
00043 // Second phase construction. Leaves, if RFs session cannot be created.
00044 // ---------------------------------------------------------------------------
00045 void CBookDb::ConstructL()
00046     {
00047     TInt err = iFsSession.Connect();
00048     if(err)
00049         User::Leave(err);
00050     }
00051 
00052 // ---------------------------------------------------------------------------
00053 // CBookDb::CBookDb()
00054 //
00055 // Constructor
00056 // ---------------------------------------------------------------------------
00057 CBookDb::CBookDb()
00058     {
00059     iOpen = EFalse;
00060     }
00061 
00062 // ---------------------------------------------------------------------------
00063 // CBookDb::OpenDbL()
00064 //
00065 // Open existing Book database for exclusive access.
00066 // ---------------------------------------------------------------------------
00067 TInt CBookDb::OpenDb(const TFileName& aExistingBookFile)
00068     {
00069     Close();
00070 
00071     if(!BaflUtils::FileExists(iFsSession, aExistingBookFile))
00072         {
00073             return KErrNotFound;
00074         }
00075 
00076         TRAPD(error, 
00077                 iFileStore = CPermanentFileStore::OpenL(iFsSession, aExistingBookFile, 
00078                         EFileRead|EFileWrite);
00079                 iFileStore->SetTypeL(iFileStore->Layout());/* Set file store type*/
00080                 iBookDb.OpenL(iFileStore,iFileStore->Root())
00081                 );
00082     if(error!=KErrNone)
00083     {
00084         return error;
00085     }
00086     
00087     iOpen = ETrue;
00088     return KErrNone;
00089     }
00090 
00091 // ---------------------------------------------------------------------------
00092 // CBookDb::CreateDbL()
00093 //
00094 // Create a new database. The database will be in exclusive access mode.
00095 // ---------------------------------------------------------------------------
00096 TInt CBookDb::CreateDb(const TFileName& aNewBookFile)
00097     {
00098     Close();
00099 
00100     // Create empty database file.
00101     TRAPD(error,
00102         iFileStore = CPermanentFileStore::ReplaceL(iFsSession, aNewBookFile, 
00103                 EFileRead|EFileWrite);
00104         iFileStore->SetTypeL(iFileStore->Layout());// Set file store type
00105         TStreamId id = iBookDb.CreateL(iFileStore);// Create stream object
00106         iFileStore->SetRootL(id);// Keep database id as root of store
00107         iFileStore->CommitL();// Complete creation by commiting
00108         // Create Book tables and indexes
00109         CreateBooksTableL();
00110         CreateBooksIndexL();
00111         );
00112     
00113     if(error!=KErrNone)
00114     {
00115         return error;
00116     }
00117     iOpen = ETrue;
00118     return KErrNone;
00119     }
00120 
00121 // ---------------------------------------------------------------------------
00122 // CBookDb::RemoveDb()
00123 //
00124 // First remove the Books table. Then remove the database file.
00125 // ---------------------------------------------------------------------------
00126 TInt CBookDb::RemoveDb(const TFileName& aExistingBookFile)
00127     {
00128     Close();
00129 
00130     if(!BaflUtils::FileExists(iFsSession, aExistingBookFile))
00131         {
00132             return KErrNotFound;
00133         }
00134 
00135     // It is enough to delete the database file directly. Because this example
00136     // demonstrates DDL statements, it first opens and drops the Books table.
00137 
00138         TInt error = OpenDb(aExistingBookFile);
00139         if(error!=KErrNone)
00140     {
00141         return error;
00142     }
00143     
00144     DropBooksTable();
00145     Close();
00146 
00147     iFsSession.Delete(aExistingBookFile);
00148     return KErrNone;
00149     }
00150 
00151 // ---------------------------------------------------------------------------
00152 // CBookDb::Close()
00153 //
00154 // Close the database.
00155 // ---------------------------------------------------------------------------
00156 TInt CBookDb::Close()
00157     {
00158     iBookDb.Close();
00159     if(iFileStore)
00160         {
00161         delete iFileStore;
00162         iFileStore = NULL;
00163         }
00164     iOpen = EFalse;
00165     return KErrNone;
00166     }
00167 
00168 // ---------------------------------------------------------------------------
00169 // CBookDb::IsOpen()
00170 //
00171 // Return open status of the database.
00172 // ---------------------------------------------------------------------------
00173 TBool CBookDb::IsOpen() const
00174     {
00175     return iOpen;
00176     }
00177 
00178 // ---------------------------------------------------------------------------
00179 // CBookDb::CreateBooksTableL()
00180 //
00181 // Creates Books table. Leaves, if the table cannot be created.
00182 // ---------------------------------------------------------------------------
00183 void CBookDb::CreateBooksTableL()
00184     {
00185 
00186     // Specify columns for Books table
00187     TDbCol authorCol(KBooksAuthorCol, EDbColText);   // Using default length
00188     TDbCol titleCol(KBooksTitleCol, EDbColText, KTitleMaxLength);
00189     titleCol.iAttributes = TDbCol::ENotNull;
00190     TDbCol descriptionCol(KBooksDescriptionCol, EDbColLongText); // Stream Data
00191 
00192     // Add the columns to column set
00193     CDbColSet* bookColSet = CDbColSet::NewLC();
00194     bookColSet->AddL(authorCol);
00195     bookColSet->AddL(titleCol);
00196     bookColSet->AddL(descriptionCol);
00197 
00198     // Create the Books table
00199     User::LeaveIfError(iBookDb.CreateTable(KBooksTable,
00200         *bookColSet));
00201     CleanupStack::PopAndDestroy(bookColSet);
00202     }
00203 
00204 // ---------------------------------------------------------------------------
00205 // CBookDb::CreateBooksIndexL()
00206 //
00207 // Creates an index for Books table. Leaves, if the index cannot be created.
00208 // ---------------------------------------------------------------------------
00209 void CBookDb::CreateBooksIndexL()
00210     {
00211     // Create index consisting of two columns
00212     TDbKeyCol authorCol(KBooksAuthorCol);
00213     TDbKeyCol titleCol(KBooksTitleCol);
00214 
00215     CDbKey* index = CDbKey::NewLC();   // create index key set
00216     index->AddL(titleCol);
00217     index->AddL(authorCol);
00218     User::LeaveIfError(iBookDb.CreateIndex(
00219         KBooksIndexName, KBooksTable, *index));
00220     CleanupStack::PopAndDestroy(index);
00221     }
00222 
00223 // ---------------------------------------------------------------------------
00224 // CBookDb::DropBooksTable()
00225 //
00226 // Drop the Books table incrementally. Uses RDbIncremental and DDL statement.
00227 // ---------------------------------------------------------------------------
00228 void CBookDb::DropBooksTable()
00229     {
00230     
00231     _LIT(KDropTable, "DROP TABLE ");
00232 
00233     // Sql: DROP TABLE Books
00234     TBuf sqlStr;
00235     sqlStr.Append(KDropTable);
00236     sqlStr.Append(KBooksTable);
00237 
00238     RDbIncremental incOp;
00239     TInt incStep = 0xFFFF;
00240     // Initialise Execution
00241     TInt incStat = incOp.Execute(iBookDb, sqlStr, incStep);
00242     while (incStep>0 && incStat==KErrNone)
00243         {
00244         incStat = incOp.Next(incStep); // Do the work
00245         }
00246     incOp.Close();
00247     }
00248 
00249 // ---------------------------------------------------------------------------
00250 // CBookDb::AddBookWithSqlL()
00251 //
00252 // Add a book to database using RDbView and SQL
00253 // ---------------------------------------------------------------------------
00254 TInt CBookDb::AddBookWithSql(const TDesC& aAuthor,
00255                          const TDesC& aTitle,
00256                          const TDesC& aDescription)
00257     {
00258 
00259     if(aAuthor.Length()==0 || aTitle.Length()==0 || aDescription.Length()==0)
00260         {
00261         return KErrGeneral;
00262         }
00263 
00264         _LIT(KSelect, "SELECT ");
00265         _LIT(KFrom, " FROM ");
00266         _LIT(KOrderBy, " ORDER BY ");
00267         _LIT(KDot, ", ");
00268 
00269     // Sql: SELECT Author, Title, Description FROM Books ORDER BY Title, Author
00270     TBuf sqlStr;
00271     
00272     sqlStr.Append(KSelect);
00273     sqlStr.Append(KBooksAuthorCol);
00274     sqlStr.Append(KDot);
00275     sqlStr.Append(KBooksTitleCol);
00276     sqlStr.Append(KDot);
00277     sqlStr.Append(KBooksDescriptionCol);
00278     sqlStr.Append(KFrom);
00279     sqlStr.Append(KBooksTable);
00280     sqlStr.Append(KOrderBy);
00281     sqlStr.Append(KBooksTitleCol);
00282     sqlStr.Append(KDot);
00283     sqlStr.Append(KBooksAuthorCol);
00284 
00285     RDbView view;    // Create a view on the database
00286     TInt error;
00287     error = view.Prepare(iBookDb, TDbQuery(sqlStr, EDbCompareFolded));
00288     if(error!=KErrNone)
00289     {
00290         return error;
00291     }
00292     error = view.EvaluateAll();
00293     if(error!=KErrNone)
00294     {
00295         return error;
00296     }
00297     RDbColWriteStream writeStream;  // Use stream to insert the description
00298     
00299     TRAP(error,
00300         view.InsertL();  // Insert a row. Column order matches sql select statement
00301         view.SetColL(1, aAuthor);
00302                 view.SetColL(2, aTitle);
00303         writeStream.OpenL(view, 3);
00304         writeStream.WriteL(aDescription);
00305         
00306         );
00307     if(error!=KErrNone)
00308     {
00309         return error;
00310     }
00311     writeStream.Close();
00312     TRAP(error, view.PutL()); // Complete insertion
00313         if(error!=KErrNone)
00314     {
00315         return error;
00316     } 
00317     view.Close();
00318     return KErrNone;
00319     }
00320 
00321 // ---------------------------------------------------------------------------
00322 // CBookDb::AddBookWithCppApiL()
00323 //
00324 // Add a book to database using RDbTable API
00325 // ---------------------------------------------------------------------------
00326 TInt CBookDb::AddBookWithCppApiL(const TDesC& aAuthor,
00327                             const TDesC& aTitle,
00328                             const TDesC& aDescription)
00329     {
00330 
00331     if(aAuthor.Length()==0 || aTitle.Length()==0 || aDescription.Length()==0)
00332         {
00333         return KErrGeneral;
00334         }
00335 
00336     // Create an updateable database table object
00337     RDbTable table;
00338     TInt err = table.Open(iBookDb, KBooksTable, table.EUpdatable);
00339     
00340     if(err!=KErrNone)
00341     {
00342         return err;
00343     }
00344     
00345         CDbColSet* booksColSet = table.ColSetL();
00346     CleanupStack::PushL(booksColSet);
00347     
00348     table.Reset();
00349     RDbColWriteStream writeStream;
00350     
00351     TRAPD(error,
00352         table.InsertL();
00353         table.SetColL(booksColSet->ColNo(KBooksAuthorCol), aAuthor); // col = 1
00354         table.SetColL(booksColSet->ColNo(KBooksTitleCol), aTitle);   // col = 2
00355         // Use a stream for the long text column
00356                 writeStream.OpenL(table, booksColSet->ColNo(KBooksDescriptionCol));
00357         writeStream.WriteL(aDescription);
00358         );
00359 
00360         if(error!=KErrNone)
00361     {
00362         return error;
00363     }   
00364         writeStream.Close();
00365         
00366     TRAP(err, table.PutL());    // Complete changes (the insertion)
00367         if(err!=KErrNone)
00368     {
00369         return err;
00370     }   
00371     
00372     CleanupStack::PopAndDestroy(booksColSet);
00373     table.Close();
00374         
00375     return KErrNone;
00376 
00377     }
00378 
00379 // ---------------------------------------------------------------------------
00380 // CBookDb::GetAllBooksL()
00381 //
00382 // Get array of all books in database. Format of each array item is:
00383 //      ||<Description></span>
<a name="l00384"></a>00384 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00385"></a><a class="code" href="class_c_book_db.html#a748adb83e450c321b2c9af57eaf029e4">00385</a> CDesCArrayFlat* <a class="code" href="class_c_book_db.html#a748adb83e450c321b2c9af57eaf029e4">CBookDb::GetAllBooksL</a>()
<a name="l00386"></a>00386     {
<a name="l00387"></a>00387     TPtrC author, title;
<a name="l00388"></a>00388     TBuf<KDescriptionMaxLength> description;
<a name="l00389"></a>00389     TBuf<KBookItemMaxLength> rowText;
<a name="l00390"></a>00390 
<a name="l00391"></a>00391     RDbTable table;
<a name="l00392"></a>00392     TInt err = table.Open(iBookDb, KBooksTable, table.EReadOnly);
<a name="l00393"></a>00393     User::LeaveIfError(err);
<a name="l00394"></a>00394 
<a name="l00395"></a>00395     CDesCArrayFlat* resultArray =
<a name="l00396"></a>00396         <span class="keyword">new</span> (ELeave)CDesC16ArrayFlat(KArrayGranularity);
<a name="l00397"></a>00397     CleanupStack::PushL(resultArray);
<a name="l00398"></a>00398 
<a name="l00399"></a>00399     table.Reset();
<a name="l00400"></a>00400     CDbColSet* colSet = table.ColSetL();
<a name="l00401"></a>00401     CleanupStack::PushL(colSet);
<a name="l00402"></a>00402 
<a name="l00403"></a>00403     <span class="keywordflow">for</span> (table.FirstL(); table.AtRow(); table.NextL())
<a name="l00404"></a>00404         {
<a name="l00405"></a>00405         description.Zero();
<a name="l00406"></a>00406         rowText.Zero();
<a name="l00407"></a>00407 
<a name="l00408"></a>00408         table.GetL();
<a name="l00409"></a>00409 
<a name="l00410"></a>00410         author.Set(table.ColDes(colSet->ColNo(KBooksAuthorCol)));
<a name="l00411"></a>00411         title.Set(table.ColDes(colSet->ColNo(KBooksTitleCol)));
<a name="l00412"></a>00412 
<a name="l00413"></a>00413         TDbColNo descrColNo = colSet->ColNo(KBooksDescriptionCol);
<a name="l00414"></a>00414         RDbColReadStream readStream;       <span class="comment">// A stream object for long columns</span>
<a name="l00415"></a>00415         readStream.OpenLC(table,descrColNo);
<a name="l00416"></a>00416         readStream.ReadL(description, table.ColLength(descrColNo));
<a name="l00417"></a>00417         readStream.Close();
<a name="l00418"></a>00418         CleanupStack::Pop(); <span class="comment">//readStream</span>
<a name="l00419"></a>00419 
<a name="l00420"></a>00420         rowText.Append(author);
<a name="l00421"></a>00421         rowText.Append(KSeparator);
<a name="l00422"></a>00422         rowText.Append(title);
<a name="l00423"></a>00423         rowText.Append(KSeparator);
<a name="l00424"></a>00424         rowText.Append(description);
<a name="l00425"></a>00425 
<a name="l00426"></a>00426         resultArray->AppendL(rowText); <span class="comment">// Copy rowText to resultArray</span>
<a name="l00427"></a>00427         }
<a name="l00428"></a>00428     CleanupStack::PopAndDestroy(colSet);
<a name="l00429"></a>00429     CleanupStack::Pop(resultArray);
<a name="l00430"></a>00430     table.Close();
<a name="l00431"></a>00431 
<a name="l00432"></a>00432     <span class="keywordflow">return</span> resultArray;
<a name="l00433"></a>00433     }
<a name="l00434"></a>00434 
<a name="l00435"></a>00435 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00436"></a>00436 <span class="comment">// CBookDb::GetABookFast()</span>
<a name="l00437"></a>00437 <span class="comment">//</span>
<a name="l00438"></a>00438 <span class="comment">// Get a book using index. Format of the result is:</span>
<a name="l00439"></a>00439 <span class="comment">//      <Author>|<Title>|<Description></span>
<a name="l00440"></a>00440 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00441"></a><a class="code" href="class_c_book_db.html#a3f4fd01c0f549c6c564955f2faa6ee62">00441</a> TInt <a class="code" href="class_c_book_db.html#a3f4fd01c0f549c6c564955f2faa6ee62">CBookDb::GetABookFast</a>(<span class="keyword">const</span> TDesC& aTitle, TDes& aResult)
<a name="l00442"></a>00442     {
<a name="l00443"></a>00443     TInt err = KErrNone;
<a name="l00444"></a>00444     TBuf<KDescriptionMaxLength> description; <span class="comment">// Only 128 first characters read</span>
<a name="l00445"></a>00445     RDbTable rowset;
<a name="l00446"></a>00446 
<a name="l00447"></a>00447     TDbSeekKey seekKey(aTitle); <span class="comment">// Initialize one-column seek key</span>
<a name="l00448"></a>00448 
<a name="l00449"></a>00449     <span class="comment">// Open view to "Books" table. Use index to browse the table.</span>
<a name="l00450"></a>00450     err = rowset.Open(iBookDb, KBooksTable, rowset.EReadOnly);
<a name="l00451"></a>00451     <span class="keywordflow">if</span>(err!=KErrNone)
<a name="l00452"></a>00452     {
<a name="l00453"></a>00453         <span class="keywordflow">return</span> err;
<a name="l00454"></a>00454     }
<a name="l00455"></a>00455     err = rowset.SetIndex(KBooksIndexName);
<a name="l00456"></a>00456     <span class="keywordflow">if</span>(err!=KErrNone)
<a name="l00457"></a>00457     {
<a name="l00458"></a>00458         <span class="keywordflow">return</span> err;
<a name="l00459"></a>00459     }
<a name="l00460"></a>00460     <span class="comment">// Query colum numbers for author, title, and description</span>
<a name="l00461"></a>00461     CDbColSet* colSet=NULL;
<a name="l00462"></a>00462     TRAP(err, colSet = rowset.ColSetL());
<a name="l00463"></a>00463     <span class="keywordflow">if</span>(err!=KErrNone)
<a name="l00464"></a>00464     {
<a name="l00465"></a>00465         <span class="keywordflow">return</span> err;
<a name="l00466"></a>00466     }
<a name="l00467"></a>00467 
<a name="l00468"></a>00468     TInt authorColumnNo = colSet->ColNo(KBooksAuthorCol);
<a name="l00469"></a>00469     TInt titleColumnNo = colSet->ColNo(KBooksTitleCol);
<a name="l00470"></a>00470     TInt descrColumnNo = colSet->ColNo(KBooksDescriptionCol);
<a name="l00471"></a>00471 
<a name="l00472"></a>00472     <span class="comment">// Search the index for aTitle</span>
<a name="l00473"></a>00473     TBool isTitle = <span class="keyword">false</span>;
<a name="l00474"></a>00474     TRAP(err, isTitle = rowset.SeekL(seekKey));
<a name="l00475"></a>00475     <span class="keywordflow">if</span>(isTitle)
<a name="l00476"></a>00476         {
<a name="l00477"></a>00477         RDbColReadStream readStream;     <span class="comment">// A stream object for long columns</span>
<a name="l00478"></a>00478         TRAPD(error, 
<a name="l00479"></a>00479                 rowset.GetL();
<a name="l00480"></a>00480                 readStream.OpenL(rowset,descrColumnNo);
<a name="l00481"></a>00481                 readStream.ReadL(description, rowset.ColLength(descrColumnNo));
<a name="l00482"></a>00482                 );
<a name="l00483"></a>00483         <span class="keywordflow">if</span>(error!=KErrNone)
<a name="l00484"></a>00484         {
<a name="l00485"></a>00485                 <span class="keywordflow">return</span> error;
<a name="l00486"></a>00486         }
<a name="l00487"></a>00487 
<a name="l00488"></a>00488         readStream.Close();
<a name="l00489"></a>00489 
<a name="l00490"></a>00490         aResult.Zero();
<a name="l00491"></a>00491         aResult.Append(rowset.ColDes(authorColumnNo));
<a name="l00492"></a>00492         aResult.Append(KSeparator);
<a name="l00493"></a>00493         aResult.Append(rowset.ColDes(titleColumnNo));
<a name="l00494"></a>00494         aResult.Append(KSeparator);
<a name="l00495"></a>00495         aResult.Append(description);
<a name="l00496"></a>00496 
<a name="l00497"></a>00497         err = KErrNone;
<a name="l00498"></a>00498         }
<a name="l00499"></a>00499     <span class="keywordflow">else</span>
<a name="l00500"></a>00500         {
<a name="l00501"></a>00501         err = KErrNotFound;
<a name="l00502"></a>00502         }
<a name="l00503"></a>00503 
<a name="l00504"></a>00504     rowset.Close();
<a name="l00505"></a>00505     <span class="keywordflow">return</span> err;
<a name="l00506"></a>00506     }
<a name="l00507"></a>00507 
<a name="l00508"></a>00508 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00509"></a>00509 <span class="comment">// CBookDb::GetBooksByKeyL()</span>
<a name="l00510"></a>00510 <span class="comment">//</span>
<a name="l00511"></a>00511 <span class="comment">// Get array of books from database according to column name and a search</span>
<a name="l00512"></a>00512 <span class="comment">// pattern. Format of each array item is:</span>
<a name="l00513"></a>00513 <span class="comment">//      <Author>|<Title>|<Description></span>
<a name="l00514"></a>00514 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00515"></a><a class="code" href="class_c_book_db.html#a6b153d0c0eb9d365b1163ec1301be78e">00515</a> CDesCArrayFlat* <a class="code" href="class_c_book_db.html#a6b153d0c0eb9d365b1163ec1301be78e">CBookDb::GetBooksByKeyL</a>(<span class="keyword">const</span> TDesC& aColumnName,
<a name="l00516"></a>00516     <span class="keyword">const</span> TDesC& aSearchString)
<a name="l00517"></a>00517     {
<a name="l00518"></a>00518 
<a name="l00519"></a>00519     TPtrC author, title;
<a name="l00520"></a>00520     TBuf<KDescriptionMaxLength> description;
<a name="l00521"></a>00521     TBuf<KBookItemMaxLength> rowText;
<a name="l00522"></a>00522 
<a name="l00523"></a>00523         <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KSelect, <span class="stringliteral">"SELECT "</span>);
<a name="l00524"></a>00524         <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KFrom, <span class="stringliteral">" FROM "</span>);
<a name="l00525"></a>00525         <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KWhere, <span class="stringliteral">" WHERE "</span>);
<a name="l00526"></a>00526         <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KLike, <span class="stringliteral">" LIKE '"</span>);
<a name="l00527"></a>00527         <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KOrderBy, <span class="stringliteral">"' ORDER BY "</span>);
<a name="l00528"></a>00528         <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KDot, <span class="stringliteral">", "</span>);
<a name="l00529"></a>00529 
<a name="l00530"></a>00530     <span class="comment">// Sql: SELECT Author, Title, Description FROM Books</span>
<a name="l00531"></a>00531     <span class="comment">//      WHERE "aColumnName LIKE aSearchString"</span>
<a name="l00532"></a>00532     <span class="comment">//      ORDER BY Title, Author</span>
<a name="l00533"></a>00533     TBuf<KCustomSqlMaxLength> sqlStr;
<a name="l00534"></a>00534     sqlStr.Append(KSelect);
<a name="l00535"></a>00535     sqlStr.Append(KBooksAuthorCol);
<a name="l00536"></a>00536     sqlStr.Append(KDot);
<a name="l00537"></a>00537     sqlStr.Append(KBooksTitleCol);
<a name="l00538"></a>00538     sqlStr.Append(KDot);
<a name="l00539"></a>00539     sqlStr.Append(KBooksDescriptionCol);
<a name="l00540"></a>00540     sqlStr.Append(KFrom);
<a name="l00541"></a>00541     sqlStr.Append(KBooksTable);
<a name="l00542"></a>00542     sqlStr.Append(KWhere);
<a name="l00543"></a>00543     sqlStr.Append(aColumnName);
<a name="l00544"></a>00544     sqlStr.Append(KLike);
<a name="l00545"></a>00545     sqlStr.Append(aSearchString);
<a name="l00546"></a>00546     sqlStr.Append(KOrderBy);
<a name="l00547"></a>00547     sqlStr.Append(KBooksTitleCol);
<a name="l00548"></a>00548     sqlStr.Append(KDot);
<a name="l00549"></a>00549     sqlStr.Append(KBooksAuthorCol);
<a name="l00550"></a>00550 
<a name="l00551"></a>00551     CDesCArrayFlat* resultArray =
<a name="l00552"></a>00552         <span class="keyword">new</span> (ELeave)CDesC16ArrayFlat(KArrayGranularity);
<a name="l00553"></a>00553     CleanupStack::PushL(resultArray);
<a name="l00554"></a>00554 
<a name="l00555"></a>00555     <span class="comment">// Create a view on the database</span>
<a name="l00556"></a>00556     RDbView view;
<a name="l00557"></a>00557     User::LeaveIfError(
<a name="l00558"></a>00558         view.Prepare(iBookDb, TDbQuery(sqlStr), view.EReadOnly));
<a name="l00559"></a>00559     User::LeaveIfError(view.EvaluateAll());
<a name="l00560"></a>00560 
<a name="l00561"></a>00561     CDbColSet* colSet = view.ColSetL();
<a name="l00562"></a>00562     CleanupStack::PushL(colSet);
<a name="l00563"></a>00563 
<a name="l00564"></a>00564     <span class="comment">// Append each result row to array</span>
<a name="l00565"></a>00565     <span class="keywordflow">for</span> (view.FirstL(); view.AtRow(); view.NextL())
<a name="l00566"></a>00566         {
<a name="l00567"></a>00567 
<a name="l00568"></a>00568         description.Zero();
<a name="l00569"></a>00569         rowText.Zero();
<a name="l00570"></a>00570 
<a name="l00571"></a>00571         view.GetL();
<a name="l00572"></a>00572 
<a name="l00573"></a>00573         author.Set(view.ColDes(colSet->ColNo(KBooksAuthorCol)));
<a name="l00574"></a>00574         title.Set(view.ColDes(colSet->ColNo(KBooksTitleCol)));
<a name="l00575"></a>00575 
<a name="l00576"></a>00576         TDbColNo descrColNo = colSet->ColNo(KBooksDescriptionCol);
<a name="l00577"></a>00577         RDbColReadStream readStream;       <span class="comment">// A stream object for long columns</span>
<a name="l00578"></a>00578         readStream.OpenLC(view, descrColNo);
<a name="l00579"></a>00579         readStream.ReadL(description, view.ColLength(descrColNo));
<a name="l00580"></a>00580         readStream.Close();
<a name="l00581"></a>00581         CleanupStack::Pop(); <span class="comment">//readStream</span>
<a name="l00582"></a>00582 
<a name="l00583"></a>00583         rowText.Append(author);
<a name="l00584"></a>00584         rowText.Append(KSeparator);
<a name="l00585"></a>00585         rowText.Append(title);
<a name="l00586"></a>00586         rowText.Append(KSeparator);
<a name="l00587"></a>00587         rowText.Append(description);
<a name="l00588"></a>00588 
<a name="l00589"></a>00589         resultArray->AppendL(rowText);
<a name="l00590"></a>00590         }
<a name="l00591"></a>00591     CleanupStack::PopAndDestroy(colSet);
<a name="l00592"></a>00592     view.Close();
<a name="l00593"></a>00593     CleanupStack::Pop(resultArray);
<a name="l00594"></a>00594 
<a name="l00595"></a>00595     <span class="keywordflow">return</span> resultArray;
<a name="l00596"></a>00596 
<a name="l00597"></a>00597     }
<a name="l00598"></a>00598 
<a name="l00599"></a>00599 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00600"></a>00600 <span class="comment">// CBookDb::RemoveBooks()</span>
<a name="l00601"></a>00601 <span class="comment">//</span>
<a name="l00602"></a>00602 <span class="comment">// Delete a book using title pattern and RDbUpdate (DML)</span>
<a name="l00603"></a>00603 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00604"></a><a class="code" href="class_c_book_db.html#ac4a202bf6ebb76155ef0dc65ece5a386">00604</a> TInt <a class="code" href="class_c_book_db.html#ac4a202bf6ebb76155ef0dc65ece5a386">CBookDb::RemoveBooks</a>(<span class="keyword">const</span> TDesC& aTitle, TInt& aResultCount)
<a name="l00605"></a>00605     {
<a name="l00606"></a>00606     RDbUpdate updOp;
<a name="l00607"></a>00607 
<a name="l00608"></a>00608         <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KDeleteFrom, <span class="stringliteral">"DELETE FROM "</span>);
<a name="l00609"></a>00609         <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KWhere, <span class="stringliteral">" WHERE "</span>);
<a name="l00610"></a>00610         <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KLike, <span class="stringliteral">" LIKE '"</span>);
<a name="l00611"></a>00611         <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KDot, <span class="stringliteral">"'"</span>);
<a name="l00612"></a>00612         
<a name="l00613"></a>00613     <span class="comment">// Sql: DELETE FROM Books WHERE Title LIKE 'aTitle'</span>
<a name="l00614"></a>00614     TBuf<KCustomSqlMaxLength> sqlStr;
<a name="l00615"></a>00615     sqlStr.Append(KDeleteFrom);
<a name="l00616"></a>00616     sqlStr.Append(KBooksTable);
<a name="l00617"></a>00617     sqlStr.Append(KWhere);
<a name="l00618"></a>00618     sqlStr.Append(KBooksTitleCol);
<a name="l00619"></a>00619     sqlStr.Append(KLike);
<a name="l00620"></a>00620     sqlStr.Append(aTitle);
<a name="l00621"></a>00621     sqlStr.Append(KDot);
<a name="l00622"></a>00622 
<a name="l00623"></a>00623     <span class="comment">// Initialize execution and perform the first step.</span>
<a name="l00624"></a>00624     <span class="comment">// Note: Execute() returns 0 (=KErrNone), but it does not affect database</span>
<a name="l00625"></a>00625     <span class="comment">//       until Next() is called.</span>
<a name="l00626"></a>00626     TInt incStat = updOp.Execute(iBookDb, sqlStr, EDbCompareFolded);
<a name="l00627"></a>00627     incStat = updOp.Next(); <span class="comment">// This will leave, if Execute() failed.</span>
<a name="l00628"></a>00628 
<a name="l00629"></a>00629     <span class="keywordflow">while</span>( incStat == 1 ) <span class="comment">// Just in case, if the operation has more steps</span>
<a name="l00630"></a>00630         {
<a name="l00631"></a>00631         incStat = updOp.Next();
<a name="l00632"></a>00632         }
<a name="l00633"></a>00633     aResultCount = updOp.RowCount();
<a name="l00634"></a>00634     updOp.Close();
<a name="l00635"></a>00635     <span class="keywordflow">return</span> incStat; <span class="comment">// KErrNone or system wide error code</span>
<a name="l00636"></a>00636     }
<a name="l00637"></a>00637 
<a name="l00638"></a>00638 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00639"></a>00639 <span class="comment">// CBookDb::RemoveAllBooks()</span>
<a name="l00640"></a>00640 <span class="comment">//</span>
<a name="l00641"></a>00641 <span class="comment">// Delete books using asynchronous API. (RDbUpdate and DML)</span>
<a name="l00642"></a>00642 <span class="comment">// This implementation is still synchronous, because it uses</span>
<a name="l00643"></a>00643 <span class="comment">// User::WaitForRequest. Normally asynchronous functionality should be hidden</span>
<a name="l00644"></a>00644 <span class="comment">// into active object and client callback interfaces.</span>
<a name="l00645"></a>00645 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00646"></a><a class="code" href="class_c_book_db.html#a96f6946ac8885c20f831300cbf0d55b0">00646</a> TInt <a class="code" href="class_c_book_db.html#a96f6946ac8885c20f831300cbf0d55b0">CBookDb::RemoveAllBooks</a>(TInt& aResultCount)
<a name="l00647"></a>00647     {
<a name="l00648"></a>00648     <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KDeleteFrom, <span class="stringliteral">"DELETE FROM "</span>);
<a name="l00649"></a>00649 
<a name="l00650"></a>00650     <span class="comment">// Sql: DELETE FROM Books</span>
<a name="l00651"></a>00651     TBuf<KCustomSqlMaxLength> sqlStr;
<a name="l00652"></a>00652     sqlStr.Append(KDeleteFrom);
<a name="l00653"></a>00653     sqlStr.Append(KBooksTable);
<a name="l00654"></a>00654 
<a name="l00655"></a>00655     RDbUpdate updOp;
<a name="l00656"></a>00656     TRequestStatus incStat(1);
<a name="l00657"></a>00657     TInt updStat = updOp.Execute(iBookDb, sqlStr, EDbCompareFolded);
<a name="l00658"></a>00658     <span class="keywordflow">while</span> (updStat==KErrNone && incStat ==1)
<a name="l00659"></a>00659         {
<a name="l00660"></a>00660         updOp.Next(incStat);           <span class="comment">// Start async operation. It returns</span>
<a name="l00661"></a>00661                                        <span class="comment">// immediately.</span>
<a name="l00662"></a>00662         User::WaitForRequest(incStat); <span class="comment">// For simplicity wait completion here.</span>
<a name="l00663"></a>00663         }
<a name="l00664"></a>00664 
<a name="l00665"></a>00665     aResultCount = updOp.RowCount();
<a name="l00666"></a>00666     updOp.Close();
<a name="l00667"></a>00667 
<a name="l00668"></a>00668     <span class="keywordflow">if</span>(updStat!=KErrNone)
<a name="l00669"></a>00669         <span class="keywordflow">return</span> updStat;       <span class="comment">// System wide error code</span>
<a name="l00670"></a>00670     <span class="keywordflow">else</span>
<a name="l00671"></a>00671         <span class="keywordflow">return</span> incStat.Int(); <span class="comment">// KErrNone or system wide error code</span>
<a name="l00672"></a>00672     }
<a name="l00673"></a>00673 
<a name="l00674"></a>00674 
<a name="l00675"></a>00675 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00676"></a>00676 <span class="comment">// CBookDb::UpdateBookTitle()</span>
<a name="l00677"></a>00677 <span class="comment">//</span>
<a name="l00678"></a>00678 <span class="comment">// Update book title using SQL UPDATE.</span>
<a name="l00679"></a>00679 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00680"></a>00680 <span class="comment">//</span>
<a name="l00681"></a><a class="code" href="class_c_book_db.html#a558090a1a44e419fd420f7113e80b310">00681</a> TInt <a class="code" href="class_c_book_db.html#a558090a1a44e419fd420f7113e80b310">CBookDb::UpdateBookTitle</a>(<span class="keyword">const</span> TDesC& aOldTitleKey,
<a name="l00682"></a>00682     <span class="keyword">const</span> TDesC& aNewTitle)
<a name="l00683"></a>00683     {
<a name="l00684"></a>00684     <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KSQLUpdateStart, <span class="stringliteral">"UPDATE Books SET Title = '"</span>);
<a name="l00685"></a>00685     <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KSQLUpdateMiddle, <span class="stringliteral">"' WHERE Title = '"</span>);
<a name="l00686"></a>00686     <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KSQLUpdateEnd, <span class="stringliteral">"'"</span>);
<a name="l00687"></a>00687 
<a name="l00688"></a>00688     TBuf<KCustomSqlMaxLength> sqlStr;
<a name="l00689"></a>00689     sqlStr.Append(KSQLUpdateStart);
<a name="l00690"></a>00690     sqlStr.Append(aNewTitle);
<a name="l00691"></a>00691     sqlStr.Append(KSQLUpdateMiddle);
<a name="l00692"></a>00692     sqlStr.Append(aOldTitleKey);
<a name="l00693"></a>00693     sqlStr.Append(KSQLUpdateEnd);
<a name="l00694"></a>00694 
<a name="l00695"></a>00695     <span class="keywordflow">return</span> iBookDb.Execute(sqlStr);
<a name="l00696"></a>00696     }
<a name="l00697"></a>00697 
<a name="l00698"></a>00698 
<a name="l00699"></a>00699 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00700"></a>00700 <span class="comment">// CBookDb::ColumnNamesAndSizesL()</span>
<a name="l00701"></a>00701 <span class="comment">//</span>
<a name="l00702"></a>00702 <span class="comment">// Get array of column names and sizes of the Books table.</span>
<a name="l00703"></a>00703 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00704"></a><a class="code" href="class_c_book_db.html#a5f13ae296de4d79beed916a416e67530">00704</a> CDesCArrayFlat* <a class="code" href="class_c_book_db.html#a5f13ae296de4d79beed916a416e67530">CBookDb::ColumnNamesAndSizesL</a>()
<a name="l00705"></a>00705     {
<a name="l00706"></a>00706     RDbTable booksTable;
<a name="l00707"></a>00707     TBuf<32> columnNameAndSize;
<a name="l00708"></a>00708     <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KDelimiter, <span class="stringliteral">": "</span>);
<a name="l00709"></a>00709     <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KNoSize,<span class="stringliteral">"No size"</span>);
<a name="l00710"></a>00710 
<a name="l00711"></a>00711     <span class="comment">// Open the Books table.</span>
<a name="l00712"></a>00712     TInt err = booksTable.Open(iBookDb, KBooksTable, booksTable.EReadOnly);
<a name="l00713"></a>00713     User::LeaveIfError(err);
<a name="l00714"></a>00714     
<a name="l00715"></a>00715     CleanupClosePushL(booksTable);  <span class="comment">// Remember to pop and close</span>
<a name="l00716"></a>00716 
<a name="l00717"></a>00717     CDesCArrayFlat* resultArray =
<a name="l00718"></a>00718         <span class="keyword">new</span> (ELeave)CDesC16ArrayFlat(KArrayGranularity);
<a name="l00719"></a>00719     CleanupStack::PushL(resultArray);
<a name="l00720"></a>00720 
<a name="l00721"></a>00721     <span class="comment">// Iterate through the colums of Books table. Extract the column name and</span>
<a name="l00722"></a>00722     <span class="comment">// column size (size only for text columns).</span>
<a name="l00723"></a>00723     <span class="comment">// Note: Description column is long text. Database limits its size</span>
<a name="l00724"></a>00724     <span class="comment">//       only by hardware. If size is queried, it is -1</span>
<a name="l00725"></a>00725     CDbColSet* colSet = booksTable.ColSetL();
<a name="l00726"></a>00726     CleanupStack::PushL(colSet);
<a name="l00727"></a>00727     TDbColSetIter colIter(*colSet);
<a name="l00728"></a>00728     <span class="keywordflow">while</span>(colIter)
<a name="l00729"></a>00729         {
<a name="l00730"></a>00730         columnNameAndSize.Zero();
<a name="l00731"></a>00731         columnNameAndSize.Append(colIter->iName);
<a name="l00732"></a>00732         columnNameAndSize.Append(KDelimiter);
<a name="l00733"></a>00733         <span class="keywordflow">if</span>(colIter->iType == EDbColText)
<a name="l00734"></a>00734             columnNameAndSize.AppendNum(colIter->iMaxLength);
<a name="l00735"></a>00735         <span class="keywordflow">else</span>
<a name="l00736"></a>00736             columnNameAndSize.Append(KNoSize);
<a name="l00737"></a>00737         resultArray->AppendL(columnNameAndSize);
<a name="l00738"></a>00738         colIter++;
<a name="l00739"></a>00739         }
<a name="l00740"></a>00740     CleanupStack::PopAndDestroy(colSet);
<a name="l00741"></a>00741     CleanupStack::Pop(resultArray);
<a name="l00742"></a>00742 
<a name="l00743"></a>00743     <span class="comment">// Pop the booksTable from cleanup stack and close it.</span>
<a name="l00744"></a>00744     CleanupStack::PopAndDestroy();
<a name="l00745"></a>00745 
<a name="l00746"></a>00746     <span class="keywordflow">return</span> resultArray;
<a name="l00747"></a>00747     }
<a name="l00748"></a>00748 
<a name="l00749"></a>00749 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00750"></a>00750 <span class="comment">// CBookDb::HasDateColumnL()</span>
<a name="l00751"></a>00751 <span class="comment">//</span>
<a name="l00752"></a>00752 <span class="comment">// Tests wheter the Books table has date column</span>
<a name="l00753"></a>00753 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00754"></a><a class="code" href="class_c_book_db.html#a60d34d3250835e8341808b33d09733bc">00754</a> TInt <a class="code" href="class_c_book_db.html#a60d34d3250835e8341808b33d09733bc">CBookDb::HasDateColumn</a>(TBool& aReturnValue)
<a name="l00755"></a>00755     {
<a name="l00756"></a>00756     RDbTable booksTable;
<a name="l00757"></a>00757     aReturnValue = EFalse;
<a name="l00758"></a>00758 
<a name="l00759"></a>00759     <span class="comment">// Open the Books table.</span>
<a name="l00760"></a>00760     TInt err = booksTable.Open(iBookDb, KBooksTable, booksTable.EReadOnly);
<a name="l00761"></a>00761     <span class="keywordflow">if</span>(err!=KErrNone)
<a name="l00762"></a>00762     {
<a name="l00763"></a>00763         <span class="keywordflow">return</span> err;
<a name="l00764"></a>00764     }
<a name="l00765"></a>00765 
<a name="l00766"></a>00766     <span class="comment">// Iterate through the colums of Books table. Check whether there is</span>
<a name="l00767"></a>00767     <span class="comment">// a 'PublishDate' column</span>
<a name="l00768"></a>00768     CDbColSet* colSet=NULL;
<a name="l00769"></a>00769     TRAP(err, colSet = booksTable.ColSetL());
<a name="l00770"></a>00770     <span class="keywordflow">if</span>(err!=KErrNone)
<a name="l00771"></a>00771     {
<a name="l00772"></a>00772         <span class="keywordflow">return</span> err;
<a name="l00773"></a>00773     }
<a name="l00774"></a>00774 
<a name="l00775"></a>00775     TDbColSetIter colIter(*colSet);
<a name="l00776"></a>00776     <span class="keywordflow">while</span>(colIter)
<a name="l00777"></a>00777         {
<a name="l00778"></a>00778         <span class="keywordflow">if</span>( (colIter->iName).Compare(KBooksDateCol) == 0) <span class="comment">// 0 = equal</span>
<a name="l00779"></a>00779             {
<a name="l00780"></a>00780             aReturnValue = ETrue;
<a name="l00781"></a>00781             <span class="keywordflow">break</span>;
<a name="l00782"></a>00782             }
<a name="l00783"></a>00783         colIter++;
<a name="l00784"></a>00784         }
<a name="l00785"></a>00785 
<a name="l00786"></a>00786     <span class="keywordflow">return</span> KErrNone;
<a name="l00787"></a>00787     }
<a name="l00788"></a>00788 
<a name="l00789"></a>00789 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00790"></a>00790 <span class="comment">// CBookDb::AddDateColumn()</span>
<a name="l00791"></a>00791 <span class="comment">//</span>
<a name="l00792"></a>00792 <span class="comment">// Adds date column to Books table (DDL).</span>
<a name="l00793"></a>00793 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00794"></a><a class="code" href="class_c_book_db.html#a72ca4025b97842c2e743b93cbf2b013a">00794</a> TInt <a class="code" href="class_c_book_db.html#a72ca4025b97842c2e743b93cbf2b013a">CBookDb::AddDateColumn</a>()
<a name="l00795"></a>00795     {
<a name="l00796"></a>00796     <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KSqlAddDate, <span class="stringliteral">"ALTER TABLE Books ADD PublishDate DATE"</span>);
<a name="l00797"></a>00797     <span class="keywordflow">return</span> iBookDb.Execute(KSqlAddDate);
<a name="l00798"></a>00798     }
<a name="l00799"></a>00799 
<a name="l00800"></a>00800 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00801"></a>00801 <span class="comment">// CBookDb::RemoveDateColumn()</span>
<a name="l00802"></a>00802 <span class="comment">//</span>
<a name="l00803"></a>00803 <span class="comment">// Removes date column from Books table (DDL).</span>
<a name="l00804"></a>00804 <span class="comment">// ---------------------------------------------------------------------------</span>
<a name="l00805"></a><a class="code" href="class_c_book_db.html#a470d106d843cea950d8c5bb8ccfeb122">00805</a> TInt <a class="code" href="class_c_book_db.html#a470d106d843cea950d8c5bb8ccfeb122">CBookDb::RemoveDateColumn</a>()
<a name="l00806"></a>00806     {
<a name="l00807"></a>00807     <a class="code" href="secureclientandserver_8h.html#a5eadd4429627d82193b37536d4faa03a">_LIT</a>(KSqlRemoveDate, <span class="stringliteral">"ALTER TABLE Books DROP PublishDate"</span>);
<a name="l00808"></a>00808     <span class="keywordflow">return</span> iBookDb.Execute(KSqlRemoveDate);
<a name="l00809"></a>00809     }
<a name="l00810"></a>00810 
</pre></div>
<hr size="1"></hr><address style="text-align: right;"><small>Generated by 
<a href="https://web.archive.org/web/20110000000000*/http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"></img></a> 1.6.2 </small></address>
     <p class="copyright">Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).<br></br> All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the <a href=" http://www.eclipse.org/legal/epl-v10.html"> Eclipse Public License
v1.0</a>.</p> 
   </div>
  </div>
  <?php include_once (CURRENT_SKIN_PATH.'/sdl_footer.html'); ?>
 </body>
</html>