]> Creatis software - creaImageIO.git/blob - src/creaImageIOSQLiteTreeHandler.cpp
7a296e65576cbd97fa2d3c0b47b482eab14fd818
[creaImageIO.git] / src / creaImageIOSQLiteTreeHandler.cpp
1 #include <creaImageIOSQLiteTreeHandler.h>
2 #include <creaImageIOSystem.h>
3 #include <creaImageIOGimmick.h>
4
5 #include "CppSQLite3.h"
6
7 #include <sys/stat.h>
8
9 #include <deque>
10
11 #include <creaWx.h>
12 #include <boost/algorithm/string.hpp>
13 using namespace crea;
14
15
16
17 namespace creaImageIO
18 {
19   using namespace tree;
20
21
22   //=============================================================
23   SQLiteTreeHandler::SQLiteTreeHandler(const std::string& filename)
24     : mFileName(filename)
25   {
26     mDB = new CppSQLite3DB;
27         mIsAdding=false;
28     //GimmickMessage(1,"SQLite version : "                 <<std::string(mDB->SQLiteVersion())<< std::endl);
29   }
30   //=============================================================
31
32   //=============================================================
33   SQLiteTreeHandler::~SQLiteTreeHandler()
34   {
35     delete mDB;
36   }
37   //=============================================================
38   
39
40   //=====================================================================
41
42
43   //=====================================================================
44   bool SQLiteTreeHandler::Open(bool writable)
45   {
46     //    std::cout << "***> SQLiteTreeHandler::Open('"<<GetFileName()<<"')"<<std::endl;
47     SetWritable(writable);
48     return DBOpen();
49   }
50
51   //=====================================================================
52   bool SQLiteTreeHandler::Create(bool writable)
53   {
54     //    std::cout << "***> SQLiteTreeHandler::New('"<<GetFileName()<<"')"<<std::endl;
55     SetWritable(writable);
56     return DBCreate();
57   }
58   //=====================================================================
59
60
61   //=====================================================================
62   bool SQLiteTreeHandler::Close()
63   {
64     return true;
65   }
66   //=====================================================================
67
68
69   //=====================================================================
70   bool SQLiteTreeHandler::Destroy()
71   {
72     return false;
73   }
74   
75   //===================================================================== 
76
77   //===================================================================== 
78   int SQLiteTreeHandler::LoadChildren(tree::Node* parent, int maxlevel)
79   {
80     if (parent==0) parent = GetTree().GetTree();
81     return DBLoadChildren(parent,maxlevel);
82   }
83   //===================================================================== 
84
85
86
87
88   //===================================================================== 
89   void SQLiteTreeHandler::UnLoad(tree::Node* n)
90   {
91   }
92   //===================================================================== 
93
94   //===================================================================== 
95   int SQLiteTreeHandler::AddBranch( const AttributeMapType& attr )
96   {
97     tree::Node* parent = DBGetParent(attr);
98     DBGraftToParent(parent,attr);
99     return (parent->GetLevel()+1);
100           
101   }
102   //===================================================================== 
103  
104
105   //===================================================================== 
106    bool SQLiteTreeHandler::Remove(tree::Node* node)
107    {
108    DBRecursiveRemoveNode(node);
109  
110     //    std::cout << "DELETE"<<std::endl;
111    bool remove=false;
112    tree::Node* parent=node->GetParent();
113     if (parent)
114       {
115         int nC = parent->RemoveChildrenFromList(node);
116         if(nC>0 && parent->GetLevel()>0)
117         {       
118                 std::stringstream out;
119                 out <<nC;
120                 SetAttribute(parent,"NumberOfChildren",out.str());
121         }
122         else
123         {
124                 remove=true;
125         }
126
127       }
128     delete node;
129         if(remove&&parent->GetLevel()>0)
130         {
131                 Remove(parent);
132         }
133     //    std::cout << "DELETE OK"<<std::endl;
134     return true;
135    }
136   
137   //===================================================================== 
138
139   //===================================================================== 
140   /// Sets an attribute of a Node
141   bool SQLiteTreeHandler::SetAttribute(tree::Node* n, 
142                                        const std::string& key,
143                                        const std::string& value)
144   {
145     if (n==0) n=GetTree().GetTree();
146     return DBSetAttribute(n,key,value);
147   }
148   //===================================================================== 
149    //===================================================================== 
150   /// Sets an attribute
151   void SQLiteTreeHandler::SetAttribute(const std::string& levelDescriptor, 
152                               const std::string& key,
153                               const std::string& value,
154                                   const std::string& searchParam, 
155                                   const std::string& searchVal)
156   {
157         DBSetAttribute(levelDescriptor,key,value,searchParam, searchVal);
158   }
159   //===================================================================== 
160   /// Deletes a tuple
161   void SQLiteTreeHandler::DeleteTuple(std::string levelDescriptor, 
162                                                                 std::string key, std::string value)
163   {
164     DBDelete(levelDescriptor,key,value);
165   }
166   //===================================================================== 
167
168
169
170
171
172
173
174
175
176
177
178
179
180   //=====================================================================
181   // SQLite DB specific methods
182   //=====================================================================
183
184
185
186
187   //=====================================================================
188   char* format_sql(const std::string& s)
189   { 
190     return sqlite3_mprintf("%q",s.c_str());
191   }
192   //=====================================================================
193
194   
195   //=====================================================================
196 #define QUERYDB(QUER,RES)                                               \
197     try                                                                 \
198       {                                                                 \
199         GimmickMessage(2,"SQL query: '"<<QUER<<"'"<<std::endl);         \
200         RES = mDB->execQuery(QUER.c_str());                             \
201       }                                                                 \
202     catch (CppSQLite3Exception& e)                                      \
203       {                                                                 \
204         GimmickError("SQLite query '"<<QUER<<"' : "                     \
205                      << e.errorCode() << ":"                            \
206                      << e.errorMessage() );                             \
207       }                                                                 \
208     
209   //=====================================================================
210   
211   //=====================================================================
212 #define UPDATEDB(UP)                                                    \
213   try                                                                   \
214     {                                                                   \
215       GimmickMessage(2,"SQL update: '"<<UP<<"'"<<std::endl);            \
216       mDB->execDML(UP.c_str());                                         \
217     }                                                                   \
218   catch (CppSQLite3Exception& e)                                        \
219     {                                                                   \
220       GimmickError("SQLite update '"<<UP<<"' Error : "                  \
221                    << e.errorCode() << ":"                              \
222                    << e.errorMessage() );                               \
223     }                                                                   
224   //=====================================================================
225
226
227   //=====================================================================
228   bool SQLiteTreeHandler::DBOpen()
229   {
230     GimmickMessage(1,"Opening SQLite database '"<<GetFileName()
231                    <<"' ... "<<std::endl);
232     // OPENING FILE
233     if (!boost::filesystem::exists(GetFileName())) 
234       {
235         return false;
236       }
237
238     try
239       {
240         mDB->open(GetFileName().c_str());
241       }
242     catch (CppSQLite3Exception& e)
243       {
244         GimmickError("Opening '"<<GetFileName()<<"' : "
245                      << e.errorCode() << ":" 
246                      << e.errorMessage());
247         return false;
248       }
249     // IMPORT TREE DESCRIPTION (AND TEST DB VALIDITY)
250     if (!DBImportTreeDescription())
251       {
252         return false;
253       }
254
255     GimmickDebugMessage(1,"Opening SQLite database '"<<GetFileName()
256                    <<"' ... OK"<<std::endl);
257     return true;
258   }
259   //=====================================================================
260
261   //=====================================================================
262   bool SQLiteTreeHandler::DBCreate()
263   {
264     GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
265                    <<"' ... "<<std::endl);
266
267     if (boost::filesystem::exists(GetFileName())) 
268       {
269         GimmickError(GetFileName()<<"' : "
270                      << "file already exists");
271         return false;
272       }
273     
274     // OPENING
275     try
276       {
277         mDB->open(GetFileName().c_str());
278       }
279     catch (CppSQLite3Exception& e)
280       {
281         GimmickError(e.errorCode() << ":" 
282                      << e.errorMessage() <<std::endl);
283         return false;
284       }
285     
286      
287     // CREATING TABLES
288     
289     std::string command;
290     // Create LEVELS table
291     command = "create table LEVELS\n";
292     command += "( Name text )\n";
293     UPDATEDB(command);
294     int l;
295     // Iterate the Levels
296     for (l=0; l<GetTree().GetNumberOfLevels(); l++)
297       {
298         command = "INSERT INTO LEVELS (Name) VALUES ('";
299         command += GetTree().GetLevelDescriptor(l).GetName();
300         command += "')";
301         UPDATEDB(command);
302         
303         // Create table of level (for level>0, i.e. not Root)
304         if (l>=0)
305           {
306             command = "CREATE TABLE ";
307             command += GetTree().GetLevelDescriptor(l).GetName();
308             command += "\n(\nID INTEGER PRIMARY KEY";
309             if (l>1) 
310               {
311                 command += ",\nPARENT_ID int not null"; 
312               }
313             SQLAppendAttributesDefinition(l,command);
314             if (l>1) 
315               {
316                 command += ",\nconstraint FK_PARENT foreign key (PARENT_ID) references ";
317                 command += GetTree().GetLevelDescriptor(l-1).GetName();
318                 command += "(ID) on delete restrict on update restrict";
319               }
320             command += "\n)";
321             UPDATEDB(command);
322             
323                 GetTree().CopyAttributeDescriptorList(l);
324             
325             // Add Attribute 'ID' to Description
326             GetTree().GetDescriptor().Add
327               (AttributeDescriptor( "ID",
328                                     "Database Identifier",
329                                     0,0,
330                                     AttributeDescriptor::PRIVATE
331                                     ),l);
332             
333             if (l>1) 
334               {
335                 // Add Attribute 'PARENT_ID' to Description
336                 GetTree().GetDescriptor().Add
337                   (AttributeDescriptor( "PARENT_ID",
338                                         "Database Parent Identifier",
339                                         0,0,
340                                         AttributeDescriptor::PRIVATE
341                                         ),l);
342               }
343             
344           }
345         
346         // Create table *_ATTRIBUTES
347         
348         command = "CREATE TABLE ";
349         command += GetTree().GetLevelDescriptor(l).GetName();
350         command += "_Attributes\n(\n";
351         command += "Key text,\n";
352         command += "Name text,\n";          
353         command += "DicomGroup int,\n";
354         command += "DicomElement int,\n";           
355         command += "Flags int\n";           
356         command += "\n)";
357         UPDATEDB(command);
358
359         // Fill the table *_ATTRIBUTES
360         LevelDescriptor::AttributeDescriptorListType::const_iterator i;
361         for (i  = GetTree().GetAttributeDescriptorList(l).begin();
362              i != GetTree().GetAttributeDescriptorList(l).end();
363              ++i)
364           {
365             
366             std::stringstream insert;
367             insert << "INSERT INTO "
368                    << GetTree().GetLevelDescriptor(l).GetName()
369                    << "_Attributes (Key,Name,DicomGroup,DicomElement,Flags) "
370                    << "VALUES ('"
371                    << i->GetKey() << "','"
372                    << i->GetName() << "',"
373                    << i->GetGroup() << ","
374                    << i->GetElement() << ","
375                    << i->GetFlags() << ");";
376             UPDATEDB(insert.str());
377           }
378
379       } // For l=0...
380
381     // Initialize the root attributes
382     GetTree().InitializeAttributeMap();
383     // Insert the root in the level 0 table 
384     DBInsert(GetTree().GetTree());
385     
386     
387     GetTree().SetChildrenLoaded(true);
388     GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
389                    <<"' ... OK"<<std::endl);
390     return true;
391   }
392   //=====================================================================
393   
394   //=====================================================================
395   void SQLiteTreeHandler::SQLAppendAttributesDefinition(int level,
396                                                         std::string& s)
397   {
398     LevelDescriptor::AttributeDescriptorListType::const_iterator i;
399     for (i  = GetTree().GetAttributeDescriptorList(level).begin();
400          i != GetTree().GetAttributeDescriptorList(level).end();
401          ++i)
402       {
403         //      if (i->second.flags==1) continue;
404         s += ",\n";
405         s += i->GetKey();
406         s += " text";
407       }
408   }
409   //=====================================================================
410   
411   
412   //=====================================================================
413   bool SQLiteTreeHandler::DBImportTreeDescription()
414   {
415     GimmickMessage(1,"Importing tree description for database ..."
416                    <<std::endl);
417
418     // Test table 'LEVELS' existence
419     if ( ! mDB->tableExists("LEVELS") )
420       {
421         GimmickMessage(1,"!! ERROR : Table 'LEVELS' does not exist"
422                        <<std::endl);
423         return false;
424       }
425
426     tree::Descriptor& desc = GetTree().GetDescriptor();
427     // clears the existing one
428     desc.Clear();
429      
430     int nblevel = 0;
431     std::string query = "SELECT * FROM LEVELS";
432     CppSQLite3Query q;
433     QUERYDB(query,q);
434
435     while (!q.eof())
436       {
437         std::string name = q.getStringField(0);
438         GimmickMessage(2," * Importing level '"<<name<<"'"<<std::endl);
439         desc.Add(LevelDescriptor(name));
440         nblevel++;
441         q.nextRow();
442       }   
443     
444     for (int level = 0; level < nblevel; ++level )
445       {
446         std::string table = GetTree().GetLevelDescriptor(level).GetName();
447         table += "_Attributes";
448         // Test table 'LEVELS' existence
449         if ( ! mDB->tableExists(table.c_str()) )
450           {
451             GimmickMessage(1,"!! ERROR : Table '"<<table<<"' does not exist"
452                            <<std::endl);
453             return false;
454           }
455         
456         std::string query = "SELECT * FROM ";
457         query += table;
458         CppSQLite3Query q;
459         QUERYDB(query,q);
460         
461         GimmickMessage(2," * Level '"
462                        <<GetTree().GetLevelDescriptor(level).GetName()
463                        <<"'"<<std::endl);
464
465         // Test that ID and PARENT_ID mandatory attributes exist
466         bool ID_found = false;
467         bool PARENT_ID_found = false;
468         if (level==0) ID_found = true;
469         if (level<=1) PARENT_ID_found = true;
470
471         while (!q.eof())
472           {
473             std::string key(q.getStringField(0));
474             std::string name(q.getStringField(1));
475             GimmickMessage(2,"  - Importing attribute '"<<key<<"' '"<<name
476                            <<"'"<<std::endl);
477             desc.Add
478               (AttributeDescriptor( key, // Key
479                                     name, // Name
480                                     q.getIntField(2), // Group
481                                     q.getIntField(3), // Element 
482                                     q.getIntField(4) // Flags
483                                     ),level);
484             if ( key == "ID" ) 
485               {
486                 ID_found = true;
487               }
488             if ( key == "PARENT_ID" ) 
489               {
490                 PARENT_ID_found = true;
491               }
492             q.nextRow();
493           }
494         
495         if ( ! (ID_found || PARENT_ID_found ) )
496           {
497             GimmickMessage(1,"!! ERROR : Table '"<<table
498                            <<"' does not contain mandatory attribute ID or PARENT_ID"
499                            <<std::endl);
500             return false;
501  
502           }
503                  GetTree().CopyAttributeDescriptorList(level);
504       }
505
506         
507     // Create the attributes table for Root (i.e. Tree)
508     LevelDescriptor::AttributeDescriptorListType::const_iterator a;
509     for (a = GetTree().GetAttributeDescriptorList(0).begin();
510          a!= GetTree().GetAttributeDescriptorList(0).end();
511          ++a)
512       {
513
514         GetTree().UnsafeSetAttribute( a->GetKey(), "" );
515       }
516
517     // Reading Root attributes
518     // Query DB
519     query = "SELECT * FROM ";
520     query += GetTree().GetLevelDescriptor(0).GetName();
521     QUERYDB(query,q);
522
523     for (int fld = 0; fld < q.numFields(); fld++)
524       {
525         GetTree().UnsafeSetAttribute(q.fieldName(fld),
526                                      q.getStringField(fld));        
527       }
528
529     GimmickMessage(1,"Importing tree description from database ... OK"
530                    <<std::endl);
531     return true;
532   }
533   //=====================================================================
534
535   //========================================================================
536   /// 
537   void SQLformat(std::string i_str, std::string &o_str)
538   {
539                 // quote must be doubled
540                 boost::algorithm::replace_all(i_str,"'","''");
541                 // Found strange strings which contained NULL char INSIDE string 
542                 int i,size=i_str.size();
543                 for (i=0;i<size;++i) 
544                 {
545                         if (i_str[i]==0) 
546                         {
547                                 i_str = i_str.substr(0,i);
548                                 break;
549                           }
550                 }
551                 o_str = i_str;
552   }
553   //========================================================================
554   
555   //=====================================================================
556   void SQLiteTreeHandler::SQLAppendAttributesValues(tree::Node* n, 
557                                                     std::string& str)
558   {
559     GimmickMessage(4,"SQLAppendAttributesValues"<<std::endl);
560     std::string atts="";
561     std::string values="";
562         std::string out ="";
563     tree::Node::AttributeMapType::iterator i;
564     for (i =  n->GetAttributeMap().begin();
565          i != n->GetAttributeMap().end();
566          i++)
567       {
568         if (i->first=="ID") 
569           {
570             continue;
571           }
572
573         atts += "'" + i->first + "'";
574         SQLformat(i->second, out);
575         values += "'" + out + "'"; 
576         atts += ",";
577         values += ",";
578         GimmickMessage(4,"'"<<i->first<<"' = '"<<i->second<<"'"<<std::endl);
579       }
580     atts[atts.size()-1]=' ';
581     values[values.size()-1]=' ';
582
583     str = "("+atts+") VALUES ("+values+")";
584     GimmickMessage(4,"Result = '"<<str<<"'"<<std::endl);
585   }
586   //=====================================================================
587
588   //=====================================================================
589   tree::Node* SQLiteTreeHandler::DBGetParent( const AttributeMapType& attr) 
590   {
591     Node* parent = GetTree().GetTree();
592     bool go_down;
593     do 
594       {
595         go_down = false;
596         // Load the children of the current parent
597         DBLoadChildren(parent);
598         // Iterate the children 
599         tree::Node::ChildrenListType::const_iterator i;
600         for (i = parent->GetChildrenList().begin();
601              i!= parent->GetChildrenList().end();
602              ++i)
603           {
604             if ( (*i)->Matches( attr ) ) 
605               {
606                 go_down = true;
607                 parent = *i;
608                 break;
609               }
610           }     
611       }
612     while (go_down);
613     return parent;
614   }
615   //=====================================================================
616
617   //=====================================================================
618   int SQLiteTreeHandler::DBLoadChildren(tree::Node* node, 
619                                         int numberoflevels)
620   {
621     if (node->GetLevel()+1 >= node->GetTree()->GetNumberOfLevels() ) 
622       return 0;
623
624     GimmickMessage(2,"Loading children of '"<<node->GetLabel()
625                    <<"'"<<std::endl);
626
627     int nbloaded = 0;
628     // If children loaded we do not have to do it but we need to recurse
629     // in order to load the children's children if necessary, and so on...
630     if (node->GetChildrenLoaded()) 
631       {
632         // Iterate the children 
633
634         tree::Node::ChildrenListType::iterator i;
635         for (i = node->GetChildrenList().begin();
636              i!= node->GetChildrenList().end();
637              ++i)
638           {
639             nbloaded += DBLoadChildren(*i,numberoflevels-1);
640           }
641         node->SetChildrenLoaded(true);
642         return nbloaded;
643
644       }
645         else
646         {
647     /// If children not loaded : do it and recurse
648
649     // Query DB
650     int level = node->GetLevel();
651     std::string query = "SELECT * FROM ";
652         
653     query += GetTree().GetLevelDescriptor(level+1).GetName();
654     if (level>0)
655       {
656         query += " WHERE PARENT_ID='" + node->GetAttribute("ID") 
657           + "'";
658       }
659 GimmickDebugMessage(1,                                  "query : '"                         <<query                                         <<std::endl);
660     CppSQLite3Query q;
661     QUERYDB(query,q);
662
663         int p=0;
664     while (!q.eof())
665       {
666
667         //      std::cout << "DBLoadCh : creating node level "<<level+1<<std::endl;
668
669         nbloaded++;
670         Node* n = new Node(node);
671         for (int fld = 0; fld < q.numFields(); fld++)
672           {
673             n->UnsafeSetAttribute(q.fieldName(fld),q.getStringField(fld));          
674           }
675
676         // recurse 
677         if ( numberoflevels != 1 ) 
678           {
679             //  msw[2].Pause();
680             nbloaded += DBLoadChildren(n, numberoflevels-1);
681             //      msw[2].Resume();
682           }
683         // next entry in db
684         q.nextRow();
685       }
686
687     node->SetChildrenLoaded(true);
688         
689     
690     //    msw[2].Pause();
691     return nbloaded;
692         }
693   }
694   //=====================================================================
695
696   //======================================================================
697   void SQLiteTreeHandler::DBInsert(tree::Node* n)
698   {
699     GimmickMessage(2,"Inserting in DB '"<<n->GetLabel()
700                    <<"'"<<std::endl);
701     std::string val;
702     SQLAppendAttributesValues(n,val);
703     std::string insert("INSERT INTO ");
704     insert += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
705     insert += " " + val + ";";
706
707     UPDATEDB(insert);
708         
709     // Store DB id of newly created node;
710     long lastrow = mDB->lastRowId();
711     std::stringstream ri;
712     ri << mDB->lastRowId();
713     n->SetAttribute("ID",ri.str());
714   }
715   //======================================================================
716
717   //======================================================================
718   /// Graft the branch defined by the attributes to the parent
719   void SQLiteTreeHandler::DBGraftToParent( tree::Node* parent, 
720                                             const AttributeMapType& attr)
721   {
722     //    std::cout <<"Grafting to parent '"<<parent->GetLabel()
723     //             <<"'"<<std::endl;
724
725     for (int level = parent->GetLevel()+1;
726          level < GetTree().GetNumberOfLevels();
727          level++)
728       {
729         // Create Node
730         tree::Node* child = new tree::Node(parent,attr);
731         child->SetChildrenLoaded(true);
732         if (level>1)
733           {
734             int nc = GetNumberOfChildren(parent)+1;
735             
736             //  std::cout<<"Number of children "<<parent->GetNumberOfChildren()<<std::endl;
737             std::stringstream out;
738             out << nc;
739             SetAttribute(parent,"NumberOfChildren",out.str());
740           }
741
742         // Set PARENT_ID if necessary 
743         if ( parent->GetLevel()>0 )
744           child->SetAttribute("PARENT_ID",parent->GetAttribute("ID"));
745         
746         // Insert in DB
747         DBInsert(child);
748         
749         // Down one level
750         parent = child;
751           }
752   }
753   //======================================================================
754
755
756   //===================================================================== 
757   /// Sets an attribute of a Node
758   bool SQLiteTreeHandler::DBSetAttribute(tree::Node* n, 
759                                          const std::string& key,
760                                          const std::string& value)
761   {
762     GimmickMessage(3,"Setting Attribute of '"<<n->GetLabel()<<
763                    "' "<<key<<"='"<<value<<"'"<<std::endl);
764
765     n->SetAttribute(key,value);
766     std::string sql = "UPDATE ";
767     sql += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
768     sql += " SET ";
769     sql += key;
770     sql += " = '";
771     sql += value;
772     sql += "' WHERE ID = '";
773     sql += n->GetAttribute("ID");
774         sql +="'";
775     //    sql += " LIMIT 1";
776     UPDATEDB(sql);
777         return true;
778   }
779
780   //===================================================================== 
781   /// Sets an attribute of a Node
782   void SQLiteTreeHandler::DBSetAttribute(const std::string& levelDescriptor, 
783                               const std::string& key,
784                               const std::string& value,
785                                   const std::string& searchParam, 
786                                   const std::string& searchVal)
787   {
788
789     std::string sql = "UPDATE ";
790     sql += levelDescriptor;
791     sql += " SET ";
792     sql += key;
793     sql += " = '";
794     sql += value;
795     sql += "' WHERE ";
796         sql += searchParam;
797         sql += " = '";
798     sql += searchVal;
799         sql += "'";
800         std::cout<<sql<<std::endl;
801     UPDATEDB(sql);
802   }
803    //=====================================================================
804   void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node)
805   {
806        
807     std::string query = "DELETE FROM ";
808         query += GetTree().GetLevelDescriptor(node->GetLevel()).GetName();
809     query += " WHERE ID='"+ node->GetAttribute("ID") + "';";
810         UPDATEDB(query);
811         
812         if(node->GetNumberOfChildren()!=0)
813         {
814                 Node::ChildrenListType::iterator i;
815                 for (i  = node->GetChildrenList().begin();
816                 i != node->GetChildrenList().end();
817                 i++)
818                 {
819                 DBRecursiveRemoveNode((*i));
820                 }
821         }
822         else if(node->GetLevel()<GetTree().GetNumberOfLevels()-1)
823         {
824                 DBRecursiveRemoveNode(node->GetLevel()+1,node->GetAttribute("ID"));
825     }
826   }
827
828   //=====================================================================
829   void SQLiteTreeHandler::DBRecursiveRemoveNode(int level, std::string parentId)
830   {
831     std::stringstream out;
832         std::stringstream result;
833         out<<"SELECT ID FROM "<<GetTree().GetLevelDescriptor(level).GetName()<<" WHERE PARENT_ID='"<<parentId<<"'";
834                 
835         CppSQLite3Query q;
836         QUERYDB(out.str(),q);
837         
838         while (!q.eof())
839           {
840             for (int fld = 0; fld < q.numFields(); fld++)
841               {
842                           result<<q.getStringField(fld)<<"#";
843               }
844             q.nextRow();
845           }
846           std::string res=result.str();
847           size_t ini=0;
848           size_t fin=0;
849           while(fin<res.size()-1)
850           {
851            fin=res.find('#',ini);
852            DBDelete(GetTree().GetLevelDescriptor(level).GetName(),"ID",res.substr(ini,fin-ini));
853           if(level<GetTree().GetNumberOfLevels()-1)
854           {
855                 DBRecursiveRemoveNode(level+1,res.substr(ini,fin-ini));
856           } 
857            ini=fin+1;
858           }
859           
860     
861   }
862
863   //=====================================================================
864   void SQLiteTreeHandler::DBDelete(std::string levelDescriptor, std::string key, std::string value)
865   {
866        
867     std::stringstream query;
868         query<<"DELETE FROM "<<levelDescriptor<<" WHERE "<<key<<"='"<<value<<"';";
869  
870     UPDATEDB(query.str());
871         GimmickDebugMessage(2," Deleting: Query: "<<query.str()<<std::endl);
872   }
873
874
875   //===================================================================== 
876   void SQLiteTreeHandler::GetAttribute(std::string levelDescriptor,
877                                                                            std::string searchParam, 
878                                                                            std::string searchVal, 
879                                                                            std::string key, 
880                                                                            std::string& result) 
881   { 
882         std::stringstream out;
883         std::stringstream results;
884         out<<"SELECT "<<key<<" FROM "<<levelDescriptor;
885         if(searchParam!="")
886         {
887                 out<<" WHERE "<<searchParam<<"='"<<searchVal<<"'";
888         }
889         
890         CppSQLite3Query q;
891         QUERYDB(out.str(),q);
892         
893         
894         while (!q.eof())
895           {
896             for (int fld = 0; fld < q.numFields(); fld++)
897               {
898                           results<<q.getStringField(fld);
899                           if(searchParam=="")
900                           {
901                                   results<<"#";
902                           }
903               }
904             q.nextRow();
905           }
906         result=results.str();
907       
908   }
909   //===================================================================== 
910   unsigned int SQLiteTreeHandler::GetNumberOfChildren(tree::Node* n) 
911   { 
912     // Query DB
913     int nb=0;
914     int level = n->GetLevel();
915
916     if(level<GetTree().GetNumberOfLevels()&& level>0)
917       {
918         std::string query = "SELECT NumberOfChildren FROM ";
919         query += GetTree().GetLevelDescriptor(level).GetName();
920         if (level>0)
921           {
922             query += " WHERE ID='" + n->GetAttribute("ID") 
923               + "'";
924           }
925         CppSQLite3Query q;
926         QUERYDB(query,q);
927         
928         
929         while (!q.eof())
930           {
931             for (int fld = 0; fld < q.numFields(); fld++)
932               {
933                 nb=q.getIntField(fld);  
934               }
935             q.nextRow();
936           }
937       }
938     /*
939     if(nb==0)
940       { 
941         nb=1;
942       }
943     */
944     return nb; 
945   }
946
947 //===================================================================== 
948 // get all attributes from database for a given file
949   void SQLiteTreeHandler::getAllAttributes(std::string i_filename, std::map<std::string, std::string> &i_results)
950   {
951           int level=GetTree().GetNumberOfLevels()-1;
952           
953           std::string search = i_filename;
954           std::string param = "FullFileName";
955           std::string name;
956
957           std::string id;
958           std::set<std::string> pid;
959           std::vector<AttributeDescriptor> attr;
960           std::vector<AttributeDescriptor>::iterator it_attr;
961           std::vector<std::string> values;
962           std::vector<std::string>::iterator it_val;
963          
964
965
966           
967           while(level>1)
968           {
969                   attr = GetTree().GetAttributeDescriptorList(level,1);
970
971                   name = GetTree().GetLevelDescriptor(level).GetName();
972                   std::vector<std::string> values;
973                   GetUpLevelNodeId(level, param,search,id);
974                   GetAttributes(name, param,search,attr, values);
975                   for(it_attr = attr.begin(), it_val = values.begin(); it_attr != attr.end(); it_attr++, it_val++)
976                   {
977                                         i_results[(*it_attr).GetKey()] = (*it_val).c_str();
978                   }
979                   search = id;
980                   param = "ID";
981                   level --;
982           }
983   }
984
985
986 //===================================================================== 
987 // get selected attributes from database for a given file
988           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)
989          {
990                  //SELECT t1.ArtistName,CDs.Title FROM Artists t1, CDs WHERE t1.ArtistID=CDs.ArtistID    
991                   std::stringstream out;
992                   std::stringstream results;
993                   out<<"SELECT ";
994                   tree::LevelDescriptor::AttributeDescriptorListType::iterator it = i_attr.begin();
995                   std::string query ="";
996                   for(; it != i_attr.end(); it++)
997                   {
998                           query += (*it).GetKey();
999                           query +=" ,";
1000                   }
1001                   query = query.substr(0, query.size()-1);
1002                   out << query;
1003                   out << "FROM "<<name;
1004                   out<<" WHERE "<<i_id <<"='"<<i_value<<"'";    
1005                   CppSQLite3Query q;
1006                   QUERYDB(out.str(),q);
1007                   while (!q.eof())
1008                   {
1009                         for (int fld = 0; fld < q.numFields(); fld++)
1010                         {
1011                                 i_results.push_back(q.getStringField(fld));
1012                         }
1013                         q.nextRow();
1014                   }
1015         }
1016
1017    void SQLiteTreeHandler::GetUpLevelNodeId(int level, const std::string& searchParam, const std::string& searchValue, std::string& parent_id) 
1018    {
1019           std::string sp=searchParam.c_str();
1020           std::string sv=searchValue.c_str();
1021           std::stringstream out;
1022           std::stringstream results;
1023           out<<"SELECT PARENT_ID FROM "<<GetTree().GetLevelDescriptor(level).GetName();
1024           out<<" WHERE "<<sp<<"='"<<sv<<"'";    
1025           CppSQLite3Query q;
1026           QUERYDB(out.str(),q);
1027           while (!q.eof())
1028           {
1029                 for (int fld = 0; fld < q.numFields(); fld++)
1030                 {
1031                         results<<q.getStringField(fld);
1032                 }
1033                 q.nextRow();
1034           }
1035           parent_id = results.str();
1036
1037   }
1038
1039
1040   //===================================================================== 
1041   void SQLiteTreeHandler::GetTopLevelNodeId(const std::string& searchParam, const std::string& searchValue, std::string& parent_id) 
1042   {
1043           int level=GetTree().GetNumberOfLevels()-1;
1044           std::string sp=searchParam.c_str();
1045           std::string sv=searchValue.c_str();
1046
1047           while(level>1)
1048           {
1049                 GetUpLevelNodeId(level, sp, sv, parent_id);
1050                 level--;
1051                 sp = "ID";
1052                 sv = parent_id;
1053           }
1054 ///*
1055 //              std::stringstream out;
1056 //              std::stringstream results;
1057 //              out<<"SELECT PARENT_ID FROM "<<GetTree().GetLevelDescriptor(level).GetName();
1058 //              out<<" WHERE "<<sp<<"='"<<sv<<"'";      
1059 //              CppSQLite3Query q;
1060 //              QUERYDB(out.str(),q);
1061 //              
1062 //              
1063 //              while (!q.eof())
1064 //              {
1065 //                      for (int fld = 0; fld < q.numFields(); fld++)
1066 //                      {
1067 //                              results<<q.getStringField(fld);
1068 //                      }
1069 //                      q.nextRow();
1070 //              }*/
1071 //              level=level-1;
1072 //              sp="ID";
1073 //              sv=results.str();
1074 //        }
1075 //        parent_id=sv;
1076
1077   }
1078
1079   //=====================================================================
1080   void SQLiteTreeHandler::RemoveEntries(const std::string i_table, 
1081                 const std::string i_attribute, 
1082                 const std::string i_operand, 
1083                 const std::string i_val)
1084     {
1085         std::stringstream query;
1086                 query<<"DELETE  FROM "<<i_table<<" WHERE "<<i_attribute<<" "<<i_operand<<" '"<<i_val<<"'";
1087         UPDATEDB(query.str());
1088         }
1089
1090         //=====================================================================
1091   void SQLiteTreeHandler::BeginTransaction()
1092     {
1093                 std::stringstream out;
1094                 out<<"begin transaction;";
1095         UPDATEDB(out.str());
1096         }
1097
1098         //=====================================================================
1099   void SQLiteTreeHandler::EndTransaction()
1100     {
1101        std::stringstream out;
1102                 out<<"commit transaction;";
1103         UPDATEDB(out.str());
1104         }
1105
1106 } // namespace creaImageIO