creaImageIOSQLiteTreeHandler.cpp

Go to the documentation of this file.
00001 #include <creaImageIOSQLiteTreeHandler.h>
00002 #include <creaImageIOSystem.h>
00003 #include <creaImageIOGimmick.h>
00004 
00005 #include "CppSQLite3.h"
00006 
00007 #include <sys/stat.h>
00008 
00009 #include <deque>
00010 
00011 #include <creaWx.h>
00012 #include <boost/algorithm/string.hpp>
00013 using namespace crea;
00014 
00015 
00016 
00017 namespace creaImageIO
00018 {
00019   using namespace tree;
00020 
00021 
00022   //=============================================================
00023   SQLiteTreeHandler::SQLiteTreeHandler(const std::string& filename)
00024     : mFileName(filename)
00025   {
00026     mDB = new CppSQLite3DB;
00027         mIsAdding=false;
00028     //GimmickMessage(1,"SQLite version : "                 <<std::string(mDB->SQLiteVersion())<< std::endl);
00029   }
00030   //=============================================================
00031 
00032   //=============================================================
00033   SQLiteTreeHandler::~SQLiteTreeHandler()
00034   {
00035     delete mDB;
00036   }
00037   //=============================================================
00038   
00039 
00040   //=====================================================================
00041 
00042 
00043   //=====================================================================
00044   bool SQLiteTreeHandler::Open(bool writable)
00045   {
00046 
00047           //sqlite3_exec(mDB, "PRAGMA synchronous=OFF ", NULL, 0, &errMsg); 
00048     SetWritable(writable);
00049     return DBOpen();
00050   }
00051 
00052   //=====================================================================
00053   bool SQLiteTreeHandler::Create(bool writable)
00054   {
00055     //    std::cout << "***> SQLiteTreeHandler::New('"<<GetFileName()<<"')"<<std::endl;
00056     SetWritable(writable);
00057     return DBCreate();
00058   }
00059   //=====================================================================
00060 
00061 
00062   //=====================================================================
00063   bool SQLiteTreeHandler::Close()
00064   {
00065     return true;
00066   }
00067   //=====================================================================
00068 
00069 
00070   //=====================================================================
00071   bool SQLiteTreeHandler::Destroy()
00072   {
00073     return false;
00074   }
00075   
00076   //===================================================================== 
00077 
00078   //===================================================================== 
00079   int SQLiteTreeHandler::LoadChildren(tree::Node* parent, int maxlevel)
00080   {      
00081         //mDB->execDML("PRAGMA synchronous=ON ");
00082     if (parent==0) parent = GetTree().GetTree();
00083     return DBLoadChildren(parent,maxlevel);
00084   }
00085   //===================================================================== 
00086 
00087 
00088 
00089 
00090   //===================================================================== 
00091   void SQLiteTreeHandler::UnLoad(tree::Node* n)
00092   {
00093   }
00094   //===================================================================== 
00095 
00096   //===================================================================== 
00097   int SQLiteTreeHandler::AddBranch( const AttributeMapType& attr )
00098   {
00099     tree::Node* parent = DBGetParent(attr);
00100     DBGraftToParent(parent,attr);
00101     return (parent->GetLevel()+1);
00102           
00103   }
00104   //===================================================================== 
00105  
00106 
00107   //===================================================================== 
00108    bool SQLiteTreeHandler::Remove(tree::Node* node)
00109    {
00110    DBRecursiveRemoveNode(node);
00111  
00112     //    std::cout << "DELETE"<<std::endl;
00113    bool remove=false;
00114    tree::Node* parent=node->GetParent();
00115     if (parent)
00116       {
00117         int nC = parent->RemoveChildrenFromList(node);
00118         if(nC>0 && parent->GetLevel()>0)
00119         {       
00120                 std::stringstream out;
00121                 out <<nC;
00122                 SetAttribute(parent,"NumberOfChildren",out.str());
00123         }
00124         else
00125         {
00126                 remove=true;
00127         }
00128 
00129       }
00130     delete node;
00131         if(remove&&parent->GetLevel()>0)
00132         {
00133                 Remove(parent);
00134         }
00135     //    std::cout << "DELETE OK"<<std::endl;
00136     return true;
00137    }
00138   
00139   //===================================================================== 
00140 
00141   //===================================================================== 
00143   bool SQLiteTreeHandler::SetAttribute(tree::Node* n, 
00144                                        const std::string& key,
00145                                        const std::string& value)
00146   {
00147     if (n==0) n=GetTree().GetTree();
00148     return DBSetAttribute(n,key,value);
00149   }
00150   //===================================================================== 
00151    //===================================================================== 
00153   void SQLiteTreeHandler::SetAttribute(const std::string& levelDescriptor, 
00154                               const std::string& key,
00155                               const std::string& value,
00156                                   const std::string& searchParam, 
00157                                   const std::string& searchVal)
00158   {
00159         DBSetAttribute(levelDescriptor,key,value,searchParam, searchVal);
00160   }
00161   //===================================================================== 
00163   void SQLiteTreeHandler::DeleteTuple(std::string levelDescriptor, 
00164                                                                 std::string key, std::string value)
00165   {
00166     DBDelete(levelDescriptor,key,value);
00167   }
00168   //===================================================================== 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182   //=====================================================================
00183   // SQLite DB specific methods
00184   //=====================================================================
00185 
00186 
00187 
00188 
00189   //=====================================================================
00190   char* format_sql(const std::string& s)
00191   { 
00192     return sqlite3_mprintf("%q",s.c_str());
00193   }
00194   //=====================================================================
00195 
00196   
00197   //=====================================================================
00198 #define QUERYDB(QUER,RES)                                               \
00199     try                                                                 \
00200       {                                                                 \
00201         GimmickMessage(2,"SQL query: '"<<QUER<<"'"<<std::endl);         \
00202         RES = mDB->execQuery(QUER.c_str());                             \
00203       }                                                                 \
00204     catch (CppSQLite3Exception& e)                                      \
00205       {                                                                 \
00206         GimmickError("SQLite query '"<<QUER<<"' : "                     \
00207                      << e.errorCode() << ":"                            \
00208                      << e.errorMessage() );                             \
00209       }                                                                 \
00210     
00211   //=====================================================================
00212   
00213   //=====================================================================
00214 #define UPDATEDB(UP)                                                    \
00215   try                                                                   \
00216     {                                                                   \
00217       GimmickMessage(2,"SQL update: '"<<UP<<"'"<<std::endl);            \
00218       mDB->execDML(UP.c_str());                                         \
00219     }                                                                   \
00220   catch (CppSQLite3Exception& e)                                        \
00221     {                                                                   \
00222       GimmickError("SQLite update '"<<UP<<"' Error : "                  \
00223                    << e.errorCode() << ":"                              \
00224                    << e.errorMessage() );                               \
00225     }                                                                   
00226   //=====================================================================
00227 
00228 
00229   //=====================================================================
00230   bool SQLiteTreeHandler::DBOpen()
00231   {
00232     GimmickMessage(1,"Opening SQLite database '"<<GetFileName()
00233                    <<"' ... "<<std::endl);
00234     // OPENING FILE
00235     if (!boost::filesystem::exists(GetFileName())) 
00236       {
00237         return false;
00238       }
00239 
00240     try
00241       {
00242         mDB->open(GetFileName().c_str());
00243         mDB->execDML("pragma synchronous=off;");
00244       }
00245     catch (CppSQLite3Exception& e)
00246       {
00247         GimmickError("Opening '"<<GetFileName()<<"' : "
00248                      << e.errorCode() << ":" 
00249                      << e.errorMessage());
00250         return false;
00251       }
00252     // IMPORT TREE DESCRIPTION (AND TEST DB VALIDITY)
00253     if (!DBImportTreeDescription())
00254       {
00255         return false;
00256       }
00257 
00258     GimmickDebugMessage(1,"Opening SQLite database '"<<GetFileName()
00259                    <<"' ... OK"<<std::endl);
00260     return true;
00261   }
00262   //=====================================================================
00263 
00264   //=====================================================================
00265   bool SQLiteTreeHandler::DBCreate()
00266   {
00267     GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
00268                    <<"' ... "<<std::endl);
00269 
00270     if (boost::filesystem::exists(GetFileName())) 
00271       {
00272         GimmickError(GetFileName()<<"' : "
00273                      << "file already exists");
00274         return false;
00275       }
00276     
00277     // OPENING
00278     try
00279       {
00280         mDB->open(GetFileName().c_str());
00281       }
00282     catch (CppSQLite3Exception& e)
00283       {
00284         GimmickError(e.errorCode() << ":" 
00285                      << e.errorMessage() <<std::endl);
00286         return false;
00287       }
00288     mDB->execDML("pragma synchronous=off;");
00289      
00290     // CREATING TABLES
00291     
00292     std::string command;
00293     // Create LEVELS table
00294     command = "create table LEVELS\n";
00295     command += "( Name text )\n";
00296     UPDATEDB(command);
00297     int l;
00298     // Iterate the Levels
00299     for (l=0; l<GetTree().GetNumberOfLevels(); l++)
00300       {
00301         command = "INSERT INTO LEVELS (Name) VALUES ('";
00302         command += GetTree().GetLevelDescriptor(l).GetName();
00303         command += "')";
00304         UPDATEDB(command);
00305         
00306         // Create table of level (for level>0, i.e. not Root)
00307         if (l>=0)
00308           {
00309             command = "CREATE TABLE ";
00310             command += GetTree().GetLevelDescriptor(l).GetName();
00311             command += "\n(\nID INTEGER PRIMARY KEY";
00312             if (l>1) 
00313               {
00314                 command += ",\nPARENT_ID int not null"; 
00315               }
00316             SQLAppendAttributesDefinition(l,command);
00317             if (l>1) 
00318               {
00319                 command += ",\nconstraint FK_PARENT foreign key (PARENT_ID) references ";
00320                 command += GetTree().GetLevelDescriptor(l-1).GetName();
00321                 command += "(ID) on delete restrict on update restrict";
00322               }
00323             command += "\n)";
00324             UPDATEDB(command);
00325             
00326                 GetTree().CopyAttributeDescriptorList(l);
00327             
00328             // Add Attribute 'ID' to Description
00329             GetTree().GetDescriptor().Add
00330               (AttributeDescriptor( "ID",
00331                                     "Database Identifier",
00332                                     0,0,
00333                                     AttributeDescriptor::PRIVATE
00334                                     ),l);
00335             
00336             if (l>1) 
00337               {
00338                 // Add Attribute 'PARENT_ID' to Description
00339                 GetTree().GetDescriptor().Add
00340                   (AttributeDescriptor( "PARENT_ID",
00341                                         "Database Parent Identifier",
00342                                         0,0,
00343                                         AttributeDescriptor::PRIVATE
00344                                         ),l);
00345               }
00346             
00347           }
00348         
00349         // Create table *_ATTRIBUTES
00350         
00351         command = "CREATE TABLE ";
00352         command += GetTree().GetLevelDescriptor(l).GetName();
00353         command += "_Attributes\n(\n";
00354         command += "Key text,\n";
00355         command += "Name text,\n";          
00356         command += "DicomGroup int,\n";
00357         command += "DicomElement int,\n";           
00358         command += "Flags int\n";           
00359         command += "\n)";
00360         UPDATEDB(command);
00361 
00362         // Fill the table *_ATTRIBUTES
00363         LevelDescriptor::AttributeDescriptorListType::const_iterator i;
00364         for (i  = GetTree().GetAttributeDescriptorList(l).begin();
00365              i != GetTree().GetAttributeDescriptorList(l).end();
00366              ++i)
00367           {
00368             
00369             std::stringstream insert;
00370             insert << "INSERT INTO "
00371                    << GetTree().GetLevelDescriptor(l).GetName()
00372                    << "_Attributes (Key,Name,DicomGroup,DicomElement,Flags) "
00373                    << "VALUES ('"
00374                    << i->GetKey() << "','"
00375                    << i->GetName() << "',"
00376                    << i->GetGroup() << ","
00377                    << i->GetElement() << ","
00378                    << i->GetFlags() << ");";
00379             UPDATEDB(insert.str());
00380           }
00381 
00382       } // For l=0...
00383 
00384     // Initialize the root attributes
00385     GetTree().InitializeAttributeMap();
00386     // Insert the root in the level 0 table 
00387     DBInsert(GetTree().GetTree());
00388     
00389     
00390     GetTree().SetChildrenLoaded(true);
00391     GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
00392                    <<"' ... OK"<<std::endl);
00393     return true;
00394   }
00395   //=====================================================================
00396   
00397   //=====================================================================
00398   void SQLiteTreeHandler::SQLAppendAttributesDefinition(int level,
00399                                                         std::string& s)
00400   {
00401     LevelDescriptor::AttributeDescriptorListType::const_iterator i;
00402     for (i  = GetTree().GetAttributeDescriptorList(level).begin();
00403          i != GetTree().GetAttributeDescriptorList(level).end();
00404          ++i)
00405       {
00406         //      if (i->second.flags==1) continue;
00407         s += ",\n";
00408         s += i->GetKey();
00409         s += " text";
00410       }
00411   }
00412   //=====================================================================
00413   
00414   
00415   //=====================================================================
00416   bool SQLiteTreeHandler::DBImportTreeDescription()
00417   {
00418     GimmickMessage(1,"Importing tree description for database ..."
00419                    <<std::endl);
00420 
00421     // Test table 'LEVELS' existence
00422     if ( ! mDB->tableExists("LEVELS") )
00423       {
00424         GimmickMessage(1,"!! ERROR : Table 'LEVELS' does not exist"
00425                        <<std::endl);
00426         return false;
00427       }
00428 
00429     tree::Descriptor& desc = GetTree().GetDescriptor();
00430     // clears the existing one
00431     desc.Clear();
00432      
00433     int nblevel = 0;
00434     std::string query = "SELECT * FROM LEVELS";
00435     CppSQLite3Query q;
00436     QUERYDB(query,q);
00437 
00438     while (!q.eof())
00439       {
00440         std::string name = q.getStringField(0);
00441         GimmickMessage(2," * Importing level '"<<name<<"'"<<std::endl);
00442         desc.Add(LevelDescriptor(name));
00443         nblevel++;
00444         q.nextRow();
00445       }   
00446     
00447     for (int level = 0; level < nblevel; ++level )
00448       {
00449         std::string table = GetTree().GetLevelDescriptor(level).GetName();
00450         table += "_Attributes";
00451         // Test table 'LEVELS' existence
00452         if ( ! mDB->tableExists(table.c_str()) )
00453           {
00454             GimmickMessage(1,"!! ERROR : Table '"<<table<<"' does not exist"
00455                            <<std::endl);
00456             return false;
00457           }
00458         
00459         std::string query = "SELECT * FROM ";
00460         query += table;
00461         CppSQLite3Query q;
00462         QUERYDB(query,q);
00463         
00464         GimmickMessage(2," * Level '"
00465                        <<GetTree().GetLevelDescriptor(level).GetName()
00466                        <<"'"<<std::endl);
00467 
00468         // Test that ID and PARENT_ID mandatory attributes exist
00469         bool ID_found = false;
00470         bool PARENT_ID_found = false;
00471         if (level==0) ID_found = true;
00472         if (level<=1) PARENT_ID_found = true;
00473 
00474         while (!q.eof())
00475           {
00476             std::string key(q.getStringField(0));
00477             std::string name(q.getStringField(1));
00478             GimmickMessage(2,"  - Importing attribute '"<<key<<"' '"<<name
00479                            <<"'"<<std::endl);
00480             desc.Add
00481               (AttributeDescriptor( key, // Key
00482                                     name, // Name
00483                                     q.getIntField(2), // Group
00484                                     q.getIntField(3), // Element 
00485                                     q.getIntField(4) // Flags
00486                                     ),level);
00487             if ( key == "ID" ) 
00488               {
00489                 ID_found = true;
00490               }
00491             if ( key == "PARENT_ID" ) 
00492               {
00493                 PARENT_ID_found = true;
00494               }
00495             q.nextRow();
00496           }
00497         
00498         if ( ! (ID_found || PARENT_ID_found ) )
00499           {
00500             GimmickMessage(1,"!! ERROR : Table '"<<table
00501                            <<"' does not contain mandatory attribute ID or PARENT_ID"
00502                            <<std::endl);
00503             return false;
00504  
00505           }
00506                  GetTree().CopyAttributeDescriptorList(level);
00507       }
00508 
00509         
00510     // Create the attributes table for Root (i.e. Tree)
00511     LevelDescriptor::AttributeDescriptorListType::const_iterator a;
00512     for (a = GetTree().GetAttributeDescriptorList(0).begin();
00513          a!= GetTree().GetAttributeDescriptorList(0).end();
00514          ++a)
00515       {
00516 
00517         GetTree().UnsafeSetAttribute( a->GetKey(), "" );
00518       }
00519 
00520     // Reading Root attributes
00521     // Query DB
00522     query = "SELECT * FROM ";
00523     query += GetTree().GetLevelDescriptor(0).GetName();
00524     QUERYDB(query,q);
00525 
00526     for (int fld = 0; fld < q.numFields(); fld++)
00527       {
00528         GetTree().UnsafeSetAttribute(q.fieldName(fld),
00529                                      q.getStringField(fld));        
00530       }
00531 
00532     GimmickMessage(1,"Importing tree description from database ... OK"
00533                    <<std::endl);
00534     return true;
00535   }
00536   //=====================================================================
00537 
00538   //========================================================================
00540   void SQLformat(std::string i_str, std::string &o_str)
00541   {
00542                 // quote must be doubled
00543                 boost::algorithm::replace_all(i_str,"'","''");
00544                 // Found strange strings which contained NULL char INSIDE string 
00545                 int i,size=i_str.size();
00546                 for (i=0;i<size;++i) 
00547                 {
00548                         if (i_str[i]==0) 
00549                         {
00550                                 i_str = i_str.substr(0,i);
00551                                 break;
00552                           }
00553                 }
00554                 o_str = i_str;
00555   }
00556   //========================================================================
00557   
00558   //=====================================================================
00559   void SQLiteTreeHandler::SQLAppendAttributesValues(tree::Node* n, 
00560                                                     std::string& str)
00561   {
00562     GimmickMessage(4,"SQLAppendAttributesValues"<<std::endl);
00563     std::string atts="";
00564     std::string values="";
00565         std::string out ="";
00566     tree::Node::AttributeMapType::iterator i;
00567     for (i =  n->GetAttributeMap().begin();
00568          i != n->GetAttributeMap().end();
00569          i++)
00570       {
00571         if (i->first=="ID") 
00572           {
00573             continue;
00574           }
00575 
00576         atts += "'" + i->first + "'";
00577         SQLformat(i->second, out);
00578         values += "'" + out + "'"; 
00579         atts += ",";
00580         values += ",";
00581         GimmickMessage(4,"'"<<i->first<<"' = '"<<i->second<<"'"<<std::endl);
00582       }
00583     atts[atts.size()-1]=' ';
00584     values[values.size()-1]=' ';
00585 
00586     str = "("+atts+") VALUES ("+values+")";
00587     GimmickMessage(4,"Result = '"<<str<<"'"<<std::endl);
00588   }
00589   //=====================================================================
00590 
00591   //=====================================================================
00592   tree::Node* SQLiteTreeHandler::DBGetParent( const AttributeMapType& attr) 
00593   {
00594     Node* parent = GetTree().GetTree();
00595     bool go_down;
00596     do 
00597       {
00598         go_down = false;
00599         // Load the children of the current parent
00600         DBLoadChildren(parent);
00601         // Iterate the children 
00602         tree::Node::ChildrenListType::const_iterator i;
00603         for (i = parent->GetChildrenList().begin();
00604              i!= parent->GetChildrenList().end();
00605              ++i)
00606           {
00607             if ( (*i)->Matches( attr ) ) 
00608               {
00609                 go_down = true;
00610                 parent = *i;
00611                 break;
00612               }
00613           }     
00614       }
00615     while (go_down);
00616     return parent;
00617   }
00618   //=====================================================================
00619 
00620   //=====================================================================
00621   int SQLiteTreeHandler::DBLoadChildren(tree::Node* node, 
00622                                         int numberoflevels)
00623   {
00624     if (node->GetLevel()+1 >= node->GetTree()->GetNumberOfLevels() ) 
00625       return 0;
00626 
00627     GimmickMessage(2,"Loading children of '"<<node->GetLabel()
00628                    <<"'"<<std::endl);
00629 
00630     int nbloaded = 0;
00631     // If children loaded we do not have to do it but we need to recurse
00632     // in order to load the children's children if necessary, and so on...
00633     if (node->GetChildrenLoaded()) 
00634       {
00635         // Iterate the children 
00636 
00637         tree::Node::ChildrenListType::iterator i;
00638         for (i = node->GetChildrenList().begin();
00639              i!= node->GetChildrenList().end();
00640              ++i)
00641           {
00642             nbloaded += DBLoadChildren(*i,numberoflevels-1);
00643           }
00644         node->SetChildrenLoaded(true);
00645         return nbloaded;
00646 
00647       }
00648         else
00649         {
00651 
00652     // Query DB
00653     int level = node->GetLevel();
00654     std::string query = "SELECT * FROM ";
00655         
00656     query += GetTree().GetLevelDescriptor(level+1).GetName();
00657     if (level>0)
00658       {
00659         query += " WHERE PARENT_ID='" + node->GetAttribute("ID") 
00660           + "'";
00661       }
00662 GimmickDebugMessage(1,                                  "query : '"                         <<query                                         <<std::endl);
00663     CppSQLite3Query q;
00664     QUERYDB(query,q);
00665 
00666         int p=0;
00667     while (!q.eof())
00668       {
00669 
00670         //      std::cout << "DBLoadCh : creating node level "<<level+1<<std::endl;
00671 
00672         nbloaded++;
00673         Node* n = new Node(node);
00674         for (int fld = 0; fld < q.numFields(); fld++)
00675           {
00676             n->UnsafeSetAttribute(q.fieldName(fld),q.getStringField(fld));          
00677           }
00678 
00679         // recurse 
00680         if ( numberoflevels != 1 ) 
00681           {
00682             //  msw[2].Pause();
00683             nbloaded += DBLoadChildren(n, numberoflevels-1);
00684             //      msw[2].Resume();
00685           }
00686         // next entry in db
00687         q.nextRow();
00688       }
00689 
00690     node->SetChildrenLoaded(true);
00691         
00692     
00693     //    msw[2].Pause();
00694     return nbloaded;
00695         }
00696   }
00697   //=====================================================================
00698 
00699   //======================================================================
00700   void SQLiteTreeHandler::DBInsert(tree::Node* n)
00701   {
00702     GimmickMessage(2,"Inserting in DB '"<<n->GetLabel()
00703                    <<"'"<<std::endl);
00704     std::string val;
00705     SQLAppendAttributesValues(n,val);
00706     std::string insert("INSERT INTO ");
00707     insert += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
00708     insert += " " + val + ";";
00709 
00710     UPDATEDB(insert);
00711         
00712     // Store DB id of newly created node;
00713     long lastrow = mDB->lastRowId();
00714     std::stringstream ri;
00715     ri << mDB->lastRowId();
00716     n->SetAttribute("ID",ri.str());
00717   }
00718   //======================================================================
00719 
00720   //======================================================================
00722   void SQLiteTreeHandler::DBGraftToParent( tree::Node* parent, 
00723                                             const AttributeMapType& attr)
00724   {
00725     //    std::cout <<"Grafting to parent '"<<parent->GetLabel()
00726     //             <<"'"<<std::endl;
00727 
00728     for (int level = parent->GetLevel()+1;
00729          level < GetTree().GetNumberOfLevels();
00730          level++)
00731       {
00732         // Create Node
00733         tree::Node* child = new tree::Node(parent,attr);
00734         child->SetChildrenLoaded(true);
00735         if (level>1)
00736           {
00737             int nc = GetNumberOfChildren(parent)+1;
00738             
00739             //  std::cout<<"Number of children "<<parent->GetNumberOfChildren()<<std::endl;
00740             std::stringstream out;
00741             out << nc;
00742             SetAttribute(parent,"NumberOfChildren",out.str());
00743           }
00744 
00745         // Set PARENT_ID if necessary 
00746         if ( parent->GetLevel()>0 )
00747           child->SetAttribute("PARENT_ID",parent->GetAttribute("ID"));
00748         
00749         // Insert in DB
00750         DBInsert(child);
00751         
00752         // Down one level
00753         parent = child;
00754           }
00755   }
00756   //======================================================================
00757 
00758 
00759   //===================================================================== 
00761   bool SQLiteTreeHandler::DBSetAttribute(tree::Node* n, 
00762                                          const std::string& key,
00763                                          const std::string& value)
00764   {
00765     GimmickMessage(3,"Setting Attribute of '"<<n->GetLabel()<<
00766                    "' "<<key<<"='"<<value<<"'"<<std::endl);
00767 
00768     n->SetAttribute(key,value);
00769     std::string sql = "UPDATE ";
00770     sql += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
00771     sql += " SET ";
00772     sql += key;
00773     sql += " = '";
00774     sql += convert(value);
00775     sql += "' WHERE ID = '";
00776     sql += n->GetAttribute("ID");
00777         sql +="'";
00778     //    sql += " LIMIT 1";
00779     UPDATEDB(sql);
00780         return true;
00781   }
00782 
00783   //===================================================================== 
00785   void SQLiteTreeHandler::DBSetAttribute(const std::string& levelDescriptor, 
00786                               const std::string& key,
00787                               const std::string& value,
00788                                   const std::string& searchParam, 
00789                                   const std::string& searchVal)
00790   {
00791 
00792     std::string sql = "UPDATE ";
00793     sql += levelDescriptor;
00794     sql += " SET ";
00795     sql += key;
00796     sql += " = '";
00797     sql += value;
00798     sql += "' WHERE ";
00799         sql += searchParam;
00800         sql += " = '";
00801     sql += searchVal;
00802         sql += "'";
00803         std::cout<<sql<<std::endl;
00804     UPDATEDB(sql);
00805   }
00806    //=====================================================================
00807   void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node)
00808   {
00809        
00810     std::string query = "DELETE FROM ";
00811         query += GetTree().GetLevelDescriptor(node->GetLevel()).GetName();
00812     query += " WHERE ID='"+ node->GetAttribute("ID") + "';";
00813         UPDATEDB(query);
00814         
00815         if(node->GetNumberOfChildren()!=0)
00816         {
00817                 Node::ChildrenListType::iterator i;
00818                 for (i  = node->GetChildrenList().begin();
00819                 i != node->GetChildrenList().end();
00820                 i++)
00821                 {
00822                 DBRecursiveRemoveNode((*i));
00823                 }
00824         }
00825         else if(node->GetLevel()<GetTree().GetNumberOfLevels()-1)
00826         {
00827                 DBRecursiveRemoveNode(node->GetLevel()+1,node->GetAttribute("ID"));
00828     }
00829   }
00830 
00831   //=====================================================================
00832   void SQLiteTreeHandler::DBRecursiveRemoveNode(int level, std::string parentId)
00833   {
00834     std::stringstream out;
00835         std::stringstream result;
00836         out<<"SELECT ID FROM "<<GetTree().GetLevelDescriptor(level).GetName()<<" WHERE PARENT_ID='"<<parentId<<"'";
00837                 
00838         CppSQLite3Query q;
00839         QUERYDB(out.str(),q);
00840         
00841         while (!q.eof())
00842           {
00843             for (int fld = 0; fld < q.numFields(); fld++)
00844               {
00845                           result<<q.getStringField(fld)<<"#";
00846               }
00847             q.nextRow();
00848           }
00849           std::string res=result.str();
00850           size_t ini=0;
00851           size_t fin=0;
00852           while(fin<res.size()-1)
00853           {
00854            fin=res.find('#',ini);
00855            DBDelete(GetTree().GetLevelDescriptor(level).GetName(),"ID",res.substr(ini,fin-ini));
00856           if(level<GetTree().GetNumberOfLevels()-1)
00857           {
00858                 DBRecursiveRemoveNode(level+1,res.substr(ini,fin-ini));
00859           } 
00860            ini=fin+1;
00861           }
00862           
00863     
00864   }
00865 
00866   //=====================================================================
00867   void SQLiteTreeHandler::DBDelete(std::string levelDescriptor, std::string key, std::string value)
00868   {
00869        
00870     std::stringstream query;
00871         query<<"DELETE FROM "<<levelDescriptor<<" WHERE "<<key<<"='"<<value<<"';";
00872  
00873     UPDATEDB(query.str());
00874         GimmickDebugMessage(2," Deleting: Query: "<<query.str()<<std::endl);
00875   }
00876 
00877 
00878   //===================================================================== 
00879   void SQLiteTreeHandler::GetAttribute(std::string levelDescriptor,
00880                                                                            std::string searchParam, 
00881                                                                            std::string searchVal, 
00882                                                                            std::string key, 
00883                                                                            std::string& result) 
00884   { 
00885         std::stringstream out;
00886         std::stringstream results;
00887         out<<"SELECT "<<key<<" FROM "<<levelDescriptor;
00888         if(searchParam!="")
00889         {
00890                 out<<" WHERE "<<searchParam<<"='"<<searchVal<<"'";
00891         }
00892         
00893         CppSQLite3Query q;
00894         QUERYDB(out.str(),q);
00895         
00896         
00897         while (!q.eof())
00898           {
00899             for (int fld = 0; fld < q.numFields(); fld++)
00900               {
00901                           results<<q.getStringField(fld);
00902                           if(searchParam=="")
00903                           {
00904                                   results<<"#";
00905                           }
00906               }
00907             q.nextRow();
00908           }
00909         result=results.str();
00910       
00911   }
00912   //===================================================================== 
00913   unsigned int SQLiteTreeHandler::GetNumberOfChildren(tree::Node* n) 
00914   { 
00915     // Query DB
00916     int nb=0;
00917     int level = n->GetLevel();
00918 
00919     if(level<GetTree().GetNumberOfLevels()&& level>0)
00920       {
00921         std::string query = "SELECT NumberOfChildren FROM ";
00922         query += GetTree().GetLevelDescriptor(level).GetName();
00923         if (level>0)
00924           {
00925             query += " WHERE ID='" + n->GetAttribute("ID") 
00926               + "'";
00927           }
00928         CppSQLite3Query q;
00929         QUERYDB(query,q);
00930         
00931         
00932         while (!q.eof())
00933           {
00934             for (int fld = 0; fld < q.numFields(); fld++)
00935               {
00936                 nb=q.getIntField(fld);  
00937               }
00938             q.nextRow();
00939           }
00940       }
00941     /*
00942     if(nb==0)
00943       { 
00944         nb=1;
00945       }
00946     */
00947     return nb; 
00948   }
00949 
00950 //===================================================================== 
00951 // get all attributes from database for a given file
00952   void SQLiteTreeHandler::getAllAttributes(std::string i_filename, std::map<std::string, std::string> &i_results)
00953   {
00954           int level=GetTree().GetNumberOfLevels()-1;
00955           
00956           std::string search = i_filename;
00957           std::string param = "FullFileName";
00958           std::string name;
00959 
00960           std::string id;
00961           std::set<std::string> pid;
00962           std::vector<AttributeDescriptor> attr;
00963           std::vector<AttributeDescriptor>::iterator it_attr;
00964           std::vector<std::string> values;
00965           std::vector<std::string>::iterator it_val;
00966          
00967 
00968 
00969           
00970           while(level>1)
00971           {
00972                   attr = GetTree().GetAttributeDescriptorList(level,1);
00973 
00974                   name = GetTree().GetLevelDescriptor(level).GetName();
00975                   std::vector<std::string> values;
00976                   GetUpLevelNodeId(level, param,search,id);
00977                   GetAttributes(name, param,search,attr, values);
00978                   for(it_attr = attr.begin(), it_val = values.begin(); it_attr != attr.end(); it_attr++, it_val++)
00979                   {
00980                                         i_results[(*it_attr).GetKey()] = (*it_val).c_str();
00981                   }
00982                   search = id;
00983                   param = "ID";
00984                   level --;
00985           }
00986   }
00987 
00988 
00989 //===================================================================== 
00990 // get selected attributes from database for a given file
00991           void SQLiteTreeHandler::GetAttributes(std::string name, std::string i_id, std::string i_value, tree::LevelDescriptor::AttributeDescriptorListType i_attr, std::vector<std::string> &i_results)
00992          {
00993                  //SELECT t1.ArtistName,CDs.Title FROM Artists t1, CDs WHERE t1.ArtistID=CDs.ArtistID    
00994                   std::stringstream out;
00995                   std::stringstream results;
00996                   out<<"SELECT ";
00997                   tree::LevelDescriptor::AttributeDescriptorListType::iterator it = i_attr.begin();
00998                   std::string query ="";
00999                   for(; it != i_attr.end(); it++)
01000                   {
01001                           query += (*it).GetKey();
01002                           query +=" ,";
01003                   }
01004                   query = query.substr(0, query.size()-1);
01005                   out << query;
01006                   out << "FROM "<<name;
01007                   out<<" WHERE "<<i_id <<"='"<<i_value<<"'";    
01008                   CppSQLite3Query q;
01009                   QUERYDB(out.str(),q);
01010                   while (!q.eof())
01011                   {
01012                         for (int fld = 0; fld < q.numFields(); fld++)
01013                         {
01014                                 i_results.push_back(q.getStringField(fld));
01015                         }
01016                         q.nextRow();
01017                   }
01018         }
01019 
01020    void SQLiteTreeHandler::GetUpLevelNodeId(int level, const std::string& searchParam, const std::string& searchValue, std::string& parent_id) 
01021    {
01022           std::string sp=searchParam.c_str();
01023           std::string sv=searchValue.c_str();
01024           std::stringstream out;
01025           std::stringstream results;
01026           out<<"SELECT PARENT_ID FROM "<<GetTree().GetLevelDescriptor(level).GetName();
01027           out<<" WHERE "<<sp<<"='"<<sv<<"'";    
01028           CppSQLite3Query q;
01029           QUERYDB(out.str(),q);
01030           while (!q.eof())
01031           {
01032                 for (int fld = 0; fld < q.numFields(); fld++)
01033                 {
01034                         results<<q.getStringField(fld);
01035                 }
01036                 q.nextRow();
01037           }
01038           parent_id = results.str();
01039 
01040   }
01041 
01042 
01043   //===================================================================== 
01044   void SQLiteTreeHandler::GetTopLevelNodeId(const std::string& searchParam, const std::string& searchValue, std::string& parent_id) 
01045   {
01046           int level=GetTree().GetNumberOfLevels()-1;
01047           std::string sp=searchParam.c_str();
01048           std::string sv=searchValue.c_str();
01049 
01050           while(level>1)
01051           {
01052                 GetUpLevelNodeId(level, sp, sv, parent_id);
01053                 level--;
01054                 sp = "ID";
01055                 sv = parent_id;
01056           }
01058 //              std::stringstream out;
01059 //              std::stringstream results;
01060 //              out<<"SELECT PARENT_ID FROM "<<GetTree().GetLevelDescriptor(level).GetName();
01061 //              out<<" WHERE "<<sp<<"='"<<sv<<"'";      
01062 //              CppSQLite3Query q;
01063 //              QUERYDB(out.str(),q);
01064 //              
01065 //              
01066 //              while (!q.eof())
01067 //              {
01068 //                      for (int fld = 0; fld < q.numFields(); fld++)
01069 //                      {
01070 //                              results<<q.getStringField(fld);
01071 //                      }
01072 //                      q.nextRow();
01073 //              }*/
01074 //              level=level-1;
01075 //              sp="ID";
01076 //              sv=results.str();
01077 //        }
01078 //        parent_id=sv;
01079 
01080   }
01081 
01082   //=====================================================================
01083   void SQLiteTreeHandler::RemoveEntries(const std::string i_table, 
01084                 const std::string i_attribute, 
01085                 const std::string i_operand, 
01086                 const std::string i_val)
01087     {
01088         std::stringstream query;
01089                 query<<"DELETE  FROM "<<i_table<<" WHERE "<<i_attribute<<" "<<i_operand<<" '"<<i_val<<"'";
01090         UPDATEDB(query.str());
01091         }
01092 
01093         //=====================================================================
01094   void SQLiteTreeHandler::BeginTransaction()
01095     {
01096                 std::stringstream out;
01097                 out<<"begin transaction;";
01098         UPDATEDB(out.str());
01099         }
01100 
01101         //=====================================================================
01102   void SQLiteTreeHandler::EndTransaction()
01103     {
01104        std::stringstream out;
01105                 out<<"commit transaction;";
01106         UPDATEDB(out.str());
01107         }
01108   const std::string SQLiteTreeHandler::convert(const std::string &i_word)
01109   {
01110           std::string temp = i_word;
01111           boost::algorithm::replace_all(temp,"'","''");
01112           return temp.c_str();
01113   }
01114 
01115 } // namespace creaImageIO