]> Creatis software - creaImageIO.git/blob - src2/creaImageIOSQLiteTreeHandler.cpp
move directory
[creaImageIO.git] / src2 / creaImageIOSQLiteTreeHandler.cpp
1 #include <creaImageIOSQLiteTreeHandler.h>
2 #include <creaImageIOSystem.h>
3 #include <creaImageIOGimmick.h>
4 #include <creaImageIOTree.h>
5
6 #include "CppSQLite3.h"
7
8 #include <sys/stat.h>
9
10 #include <deque>
11
12 #include <creaWx.h>
13 #include <boost/algorithm/string.hpp>
14 using namespace crea;
15
16
17
18 namespace creaImageIO
19 {
20   using namespace tree;
21
22
23   //=============================================================
24   SQLiteTreeHandler::SQLiteTreeHandler(const std::string& filename)
25     : mFileName(filename)
26   {
27     mDB = new CppSQLite3DB;
28         mIsAdding=false;
29     //GimmickMessage(1,"SQLite version : "                 <<std::string(mDB->SQLiteVersion())<< std::endl);
30   }
31   //=============================================================
32
33   //=============================================================
34   SQLiteTreeHandler::~SQLiteTreeHandler()
35   {
36     delete mDB;
37   }
38   //=============================================================
39   
40
41   //=====================================================================
42
43
44   //=====================================================================
45   bool SQLiteTreeHandler::Open(bool writable)
46   {
47     //    std::cout << "***> SQLiteTreeHandler::Open('"<<GetFileName()<<"')"<<std::endl;
48     SetWritable(writable);
49     return DBOpen();
50   }
51
52   //=====================================================================
53   bool SQLiteTreeHandler::Create(bool writable)
54   {
55     //    std::cout << "***> SQLiteTreeHandler::New('"<<GetFileName()<<"')"<<std::endl;
56     SetWritable(writable);
57     return DBCreate();
58   }
59   //=====================================================================
60
61
62   //=====================================================================
63   bool SQLiteTreeHandler::Close()
64   {
65     return true;
66   }
67   //=====================================================================
68
69
70   //=====================================================================
71   bool SQLiteTreeHandler::Destroy()
72   {
73     return false;
74   }
75   
76   //===================================================================== 
77
78   //===================================================================== 
79   int SQLiteTreeHandler::LoadChildren(tree::Node* parent, int maxlevel)
80   {
81     if (parent==0) parent = GetTree().GetTree();
82     return DBLoadChildren(parent,maxlevel);
83   }
84   //===================================================================== 
85
86
87
88
89   //===================================================================== 
90   void SQLiteTreeHandler::UnLoad(tree::Node* n)
91   {
92   }
93   //===================================================================== 
94
95   //===================================================================== 
96   int SQLiteTreeHandler::AddBranch( const AttributeMapType& attr )
97   {
98     tree::Node* parent = DBGetParent(attr);
99     DBGraftToParent(parent,attr);
100     return (parent->GetLevel()+1);
101           
102   }
103   //===================================================================== 
104  
105
106   //===================================================================== 
107    bool SQLiteTreeHandler::Remove(tree::Node* node)
108    {
109    DBRecursiveRemoveNode(node);
110  
111     //    std::cout << "DELETE"<<std::endl;
112    bool remove=false;
113    tree::Node* parent=node->GetParent();
114     if (parent)
115       {
116         int nC = parent->RemoveChildrenFromList(node);
117         if(nC>0 && parent->GetLevel()>0)
118         {       
119                 std::stringstream out;
120                 out <<nC;
121                 SetAttribute(parent,"NumberOfChildren",out.str());
122         }
123         else
124         {
125                 remove=true;
126         }
127
128       }
129     delete node;
130         if(remove&&parent->GetLevel()>0)
131         {
132                 Remove(parent);
133         }
134     //    std::cout << "DELETE OK"<<std::endl;
135     return true;
136    }
137   
138   //===================================================================== 
139
140   //===================================================================== 
141   /// Sets an attribute of a Node
142   bool SQLiteTreeHandler::SetAttribute(tree::Node* n, 
143                                        const std::string& key,
144                                        const std::string& value)
145   {
146     if (n==0) n=GetTree().GetTree();
147     return DBSetAttribute(n,key,value);
148   }
149   //===================================================================== 
150    //===================================================================== 
151   /// Sets an attribute
152   void SQLiteTreeHandler::SetAttribute(const std::string& levelDescriptor, 
153                               const std::string& key,
154                               const std::string& value,
155                                   const std::string& searchParam, 
156                                   const std::string& searchVal)
157   {
158         DBSetAttribute(levelDescriptor,key,value,searchParam, searchVal);
159   }
160   //===================================================================== 
161   /// Deletes a tuple
162   void SQLiteTreeHandler::DeleteTuple(std::string levelDescriptor, 
163                                                                 std::string key, std::string value)
164   {
165     DBDelete(levelDescriptor,key,value);
166   }
167   //===================================================================== 
168
169
170
171
172
173
174
175
176
177
178
179
180
181   //=====================================================================
182   // SQLite DB specific methods
183   //=====================================================================
184
185
186
187
188   //=====================================================================
189   char* format_sql(const std::string& s)
190   { 
191     return sqlite3_mprintf("%q",s.c_str());
192   }
193   //=====================================================================
194
195   
196   //=====================================================================
197 #define QUERYDB(QUER,RES)                                               \
198     try                                                                 \
199       {                                                                 \
200         GimmickMessage(2,"SQL query: '"<<QUER<<"'"<<std::endl);         \
201         RES = mDB->execQuery(QUER.c_str());                             \
202       }                                                                 \
203     catch (CppSQLite3Exception& e)                                      \
204       {                                                                 \
205         GimmickError("SQLite query '"<<QUER<<"' : "                     \
206                      << e.errorCode() << ":"                            \
207                      << e.errorMessage() );                             \
208       }                                                                 \
209     
210   //=====================================================================
211   
212   //=====================================================================
213 #define UPDATEDB(UP)                                                    \
214   try                                                                   \
215     {                                                                   \
216       GimmickMessage(2,"SQL update: '"<<UP<<"'"<<std::endl);            \
217       mDB->execDML(UP.c_str());                                         \
218     }                                                                   \
219   catch (CppSQLite3Exception& e)                                        \
220     {                                                                   \
221       GimmickError("SQLite update '"<<UP<<"' Error : "                  \
222                    << e.errorCode() << ":"                              \
223                    << e.errorMessage() );                               \
224     }                                                                   
225   //=====================================================================
226
227
228   //=====================================================================
229   bool SQLiteTreeHandler::DBOpen()
230   {
231     GimmickMessage(1,"Opening SQLite database '"<<GetFileName()
232                    <<"' ... "<<std::endl);
233     // OPENING FILE
234     if (!boost::filesystem::exists(GetFileName())) 
235       {
236         return false;
237       }
238
239     try
240       {
241         mDB->open(GetFileName().c_str());
242       }
243     catch (CppSQLite3Exception& e)
244       {
245         GimmickError("Opening '"<<GetFileName()<<"' : "
246                      << e.errorCode() << ":" 
247                      << e.errorMessage());
248         return false;
249       }
250     // IMPORT TREE DESCRIPTION (AND TEST DB VALIDITY)
251     if (!DBImportTreeDescription())
252       {
253         return false;
254       }
255
256     GimmickDebugMessage(1,"Opening SQLite database '"<<GetFileName()
257                    <<"' ... OK"<<std::endl);
258     return true;
259   }
260   //=====================================================================
261
262   //=====================================================================
263   bool SQLiteTreeHandler::DBCreate()
264   {
265     GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
266                    <<"' ... "<<std::endl);
267
268     if (boost::filesystem::exists(GetFileName())) 
269       {
270         GimmickError(GetFileName()<<"' : "
271                      << "file already exists");
272         return false;
273       }
274     
275     // OPENING
276     try
277       {
278         mDB->open(GetFileName().c_str());
279       }
280     catch (CppSQLite3Exception& e)
281       {
282         GimmickError(e.errorCode() << ":" 
283                      << e.errorMessage() <<std::endl);
284         return false;
285       }
286     
287      
288     // CREATING TABLES
289     
290     std::string command;
291     // Create LEVELS table
292     command = "create table LEVELS\n";
293     command += "( Name text )\n";
294     UPDATEDB(command);
295     int l;
296     // Iterate the Levels
297     for (l=0; l<GetTree().GetNumberOfLevels(); l++)
298       {
299         command = "INSERT INTO LEVELS (Name) VALUES ('";
300         command += GetTree().GetLevelDescriptor(l).GetName();
301         command += "')";
302         UPDATEDB(command);
303         
304         // Create table of level (for level>0, i.e. not Root)
305         if (l>=0)
306           {
307             command = "CREATE TABLE ";
308             command += GetTree().GetLevelDescriptor(l).GetName();
309             command += "\n(\nID INTEGER PRIMARY KEY";
310             if (l>1) 
311               {
312                 command += ",\nPARENT_ID int not null"; 
313               }
314             SQLAppendAttributesDefinition(l,command);
315             if (l>1) 
316               {
317                 command += ",\nconstraint FK_PARENT foreign key (PARENT_ID) references ";
318                 command += GetTree().GetLevelDescriptor(l-1).GetName();
319                 command += "(ID) on delete restrict on update restrict";
320               }
321             command += "\n)";
322             UPDATEDB(command);
323             
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       }
504
505         
506     // Create the attributes table for Root (i.e. Tree)
507     LevelDescriptor::AttributeDescriptorListType::const_iterator a;
508     for (a = GetTree().GetAttributeDescriptorList(0).begin();
509          a!= GetTree().GetAttributeDescriptorList(0).end();
510          ++a)
511       {
512
513         GetTree().UnsafeSetAttribute( a->GetKey(), "" );
514       }
515
516     // Reading Root attributes
517     // Query DB
518     query = "SELECT * FROM ";
519     query += GetTree().GetLevelDescriptor(0).GetName();
520     QUERYDB(query,q);
521
522     for (int fld = 0; fld < q.numFields(); fld++)
523       {
524         GetTree().UnsafeSetAttribute(q.fieldName(fld),
525                                      q.getStringField(fld));        
526       }
527
528     GimmickMessage(1,"Importing tree description from database ... OK"
529                    <<std::endl);
530     return true;
531   }
532   //=====================================================================
533
534   //========================================================================
535   /// 
536   void SQLformat(std::string i_str, std::string &o_str)
537   {
538                 // quote must be doubled
539                 boost::algorithm::replace_all(i_str,"'","''");
540                 // Found strange strings which contained NULL char INSIDE string 
541                 int i,size=i_str.size();
542                 for (i=0;i<size;++i) 
543                 {
544                         if (i_str[i]==0) 
545                         {
546                                 i_str = i_str.substr(0,i);
547                                 break;
548                           }
549                 }
550                 o_str = i_str;
551   }
552   //========================================================================
553   
554   //=====================================================================
555   void SQLiteTreeHandler::SQLAppendAttributesValues(tree::Node* n, 
556                                                     std::string& str)
557   {
558     GimmickMessage(4,"SQLAppendAttributesValues"<<std::endl);
559     std::string atts="";
560     std::string values="";
561         std::string out ="";
562     tree::Node::AttributeMapType::iterator i;
563     for (i =  n->GetAttributeMap().begin();
564          i != n->GetAttributeMap().end();
565          i++)
566       {
567         if (i->first=="ID") 
568           {
569             continue;
570           }
571
572         atts += "'" + i->first + "'";
573         SQLformat(i->second, out);
574         values += "'" + out + "'"; 
575         atts += ",";
576         values += ",";
577         GimmickMessage(4,"'"<<i->first<<"' = '"<<i->second<<"'"<<std::endl);
578       }
579     atts[atts.size()-1]=' ';
580     values[values.size()-1]=' ';
581
582     str = "("+atts+") VALUES ("+values+")";
583     GimmickMessage(4,"Result = '"<<str<<"'"<<std::endl);
584   }
585   //=====================================================================
586
587   //=====================================================================
588   tree::Node* SQLiteTreeHandler::DBGetParent( const AttributeMapType& attr) 
589   {
590     Node* parent = GetTree().GetTree();
591     bool go_down;
592     do 
593       {
594         go_down = false;
595         // Load the children of the current parent
596         DBLoadChildren(parent);
597         // Iterate the children 
598         tree::Node::ChildrenListType::const_iterator i;
599         for (i = parent->GetChildrenList().begin();
600              i!= parent->GetChildrenList().end();
601              ++i)
602           {
603             if ( (*i)->Matches( attr ) ) 
604               {
605                 go_down = true;
606                 parent = *i;
607                 break;
608               }
609           }     
610       }
611     while (go_down);
612     return parent;
613   }
614   //=====================================================================
615
616   //=====================================================================
617   int SQLiteTreeHandler::DBLoadChildren(tree::Node* node, 
618                                         int numberoflevels)
619   {
620     if (node->GetLevel()+1 >= node->GetTree()->GetNumberOfLevels() ) 
621       return 0;
622
623     GimmickMessage(2,"Loading children of '"<<node->GetLabel()
624                    <<"'"<<std::endl);
625
626     int nbloaded = 0;
627     // If children loaded we do not have to do it but we need to recurse
628     // in order to load the children's children if necessary, and so on...
629     if (node->GetChildrenLoaded()) 
630       {
631         // Iterate the children 
632
633         tree::Node::ChildrenListType::iterator i;
634         for (i = node->GetChildrenList().begin();
635              i!= node->GetChildrenList().end();
636              ++i)
637           {
638             nbloaded += DBLoadChildren(*i,numberoflevels-1);
639           }
640         node->SetChildrenLoaded(true);
641         return nbloaded;
642
643       }
644         else
645         {
646     /// If children not loaded : do it and recurse
647
648     // Query DB
649     int level = node->GetLevel();
650     std::string query = "SELECT * FROM ";
651         
652     query += GetTree().GetLevelDescriptor(level+1).GetName();
653     if (level>0)
654       {
655         query += " WHERE PARENT_ID='" + node->GetAttribute("ID") 
656           + "'";
657       }
658 GimmickDebugMessage(1,                                  "query : '"                         <<query                                         <<std::endl);
659     CppSQLite3Query q;
660     QUERYDB(query,q);
661
662         int p=0;
663     while (!q.eof())
664       {
665
666         //      std::cout << "DBLoadCh : creating node level "<<level+1<<std::endl;
667
668         nbloaded++;
669         Node* n = new Node(node);
670         for (int fld = 0; fld < q.numFields(); fld++)
671           {
672             n->UnsafeSetAttribute(q.fieldName(fld),q.getStringField(fld));          
673           }
674
675         // recurse 
676         if ( numberoflevels != 1 ) 
677           {
678             //  msw[2].Pause();
679             nbloaded += DBLoadChildren(n, numberoflevels-1);
680             //      msw[2].Resume();
681           }
682         // next entry in db
683         q.nextRow();
684       }
685
686     node->SetChildrenLoaded(true);
687         
688     
689     //    msw[2].Pause();
690     return nbloaded;
691         }
692   }
693   //=====================================================================
694
695   //======================================================================
696   void SQLiteTreeHandler::DBInsert(tree::Node* n)
697   {
698     GimmickMessage(2,"Inserting in DB '"<<n->GetLabel()
699                    <<"'"<<std::endl);
700     std::string val;
701     SQLAppendAttributesValues(n,val);
702     std::string insert("INSERT INTO ");
703     insert += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
704     insert += " " + val + ";";
705
706     UPDATEDB(insert);
707         
708     // Store DB id of newly created node;
709     long lastrow = mDB->lastRowId();
710     std::stringstream ri;
711     ri << mDB->lastRowId();
712     n->SetAttribute("ID",ri.str());
713   }
714   //======================================================================
715
716   //======================================================================
717   /// Graft the branch defined by the attributes to the parent
718   void SQLiteTreeHandler::DBGraftToParent( tree::Node* parent, 
719                                             const AttributeMapType& attr)
720   {
721     //    std::cout <<"Grafting to parent '"<<parent->GetLabel()
722     //             <<"'"<<std::endl;
723
724     for (int level = parent->GetLevel()+1;
725          level < GetTree().GetNumberOfLevels();
726          level++)
727       {
728         // Create Node
729         tree::Node* child = new tree::Node(parent,attr);
730         child->SetChildrenLoaded(true);
731         if (level>1)
732           {
733             int nc = GetNumberOfChildren(parent)+1;
734             
735             //  std::cout<<"Number of children "<<parent->GetNumberOfChildren()<<std::endl;
736             std::stringstream out;
737             out << nc;
738             SetAttribute(parent,"NumberOfChildren",out.str());
739           }
740
741         // Set PARENT_ID if necessary 
742         if ( parent->GetLevel()>0 )
743           child->SetAttribute("PARENT_ID",parent->GetAttribute("ID"));
744         
745         // Insert in DB
746         DBInsert(child);
747         
748         // Down one level
749         parent = child;
750           }
751   }
752   //======================================================================
753
754
755   //===================================================================== 
756   /// Sets an attribute of a Node
757   bool SQLiteTreeHandler::DBSetAttribute(tree::Node* n, 
758                                          const std::string& key,
759                                          const std::string& value)
760   {
761     GimmickMessage(3,"Setting Attribute of '"<<n->GetLabel()<<
762                    "' "<<key<<"='"<<value<<"'"<<std::endl);
763
764     n->SetAttribute(key,value);
765     std::string sql = "UPDATE ";
766     sql += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
767     sql += " SET ";
768     sql += key;
769     sql += " = '";
770     sql += value;
771     sql += "' WHERE ID = '";
772     sql += n->GetAttribute("ID");
773         sql +="'";
774     //    sql += " LIMIT 1";
775     UPDATEDB(sql);
776         return true;
777   }
778
779   //===================================================================== 
780   /// Sets an attribute of a Node
781   void SQLiteTreeHandler::DBSetAttribute(const std::string& levelDescriptor, 
782                               const std::string& key,
783                               const std::string& value,
784                                   const std::string& searchParam, 
785                                   const std::string& searchVal)
786   {
787
788     std::string sql = "UPDATE ";
789     sql += levelDescriptor;
790     sql += " SET ";
791     sql += key;
792     sql += " = '";
793     sql += value;
794     sql += "' WHERE ";
795         sql += searchParam;
796         sql += " = '";
797     sql += searchVal;
798         sql += "'";
799         std::cout<<sql<<std::endl;
800     UPDATEDB(sql);
801   }
802    //=====================================================================
803   void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node)
804   {
805        
806     std::string query = "DELETE FROM ";
807    
808
809         query += GetTree().GetLevelDescriptor(node->GetLevel()).GetName();
810         
811     query += " WHERE ID='"+ node->GetAttribute("ID") + "';";
812  
813     UPDATEDB(query);
814         GimmickDebugMessage(2,
815                             " Deleting '"
816                                 <<node->GetLabel()<<"' with ID '"
817                             <<node->GetAttribute("ID")
818                             <<"' in level "<< GetTree().GetLevelDescriptor(node->GetLevel()).GetName()
819                             <<std::endl);
820
821
822         if(node->GetNumberOfChildren()!=0)
823         {
824                 Node::ChildrenListType::iterator i;
825                 for (i  = node->GetChildrenList().begin();
826                 i != node->GetChildrenList().end();
827                 i++)
828                 {
829                 DBRecursiveRemoveNode((*i));
830                 }
831         }
832         else if(node->GetLevel()<GetTree().GetNumberOfLevels()-1)
833         {
834                 DBRecursiveRemoveNode(node->GetLevel()+1,node->GetAttribute("ID"));
835     }
836   }
837
838   //=====================================================================
839   void SQLiteTreeHandler::DBRecursiveRemoveNode(int level, std::string parentId)
840   {
841     std::stringstream out;
842         std::stringstream result;
843         out<<"SELECT ID FROM "<<GetTree().GetLevelDescriptor(level).GetName()<<" WHERE PARENT_ID='"<<parentId<<"'";
844                 
845         CppSQLite3Query q;
846         QUERYDB(out.str(),q);
847         
848         while (!q.eof())
849           {
850             for (int fld = 0; fld < q.numFields(); fld++)
851               {
852                           result<<q.getStringField(fld)<<"#";
853               }
854             q.nextRow();
855           }
856           std::string res=result.str();
857           size_t ini=0;
858           size_t fin=0;
859           while(fin<res.size()-1)
860           {
861            fin=res.find('#',ini);
862            DBDelete(GetTree().GetLevelDescriptor(level).GetName(),"ID",res.substr(ini,fin-ini));
863           if(level<GetTree().GetNumberOfLevels()-1)
864           {
865                 DBRecursiveRemoveNode(level+1,res.substr(ini,fin-ini));
866           } 
867            ini=fin+1;
868           }
869           
870     
871   }
872
873   //=====================================================================
874   void SQLiteTreeHandler::DBDelete(std::string levelDescriptor, std::string key, std::string value)
875   {
876        
877     std::stringstream query;
878         query<<"DELETE FROM "<<levelDescriptor<<" WHERE "<<key<<"='"<<value<<"';";
879  
880     UPDATEDB(query.str());
881         GimmickDebugMessage(2," Deleting: Query: "<<query.str()<<std::endl);
882   }
883
884
885   //===================================================================== 
886   void SQLiteTreeHandler::GetAttribute(std::string levelDescriptor,
887                                                                            std::string searchParam, 
888                                                                            std::string searchVal, 
889                                                                            std::string key, 
890                                                                            std::string& result) 
891   { 
892         std::stringstream out;
893         std::stringstream results;
894         out<<"SELECT "<<key<<" FROM "<<levelDescriptor;
895         if(searchParam!="")
896         {
897                 out<<" WHERE "<<searchParam<<"='"<<searchVal<<"'";
898         }
899         
900         CppSQLite3Query q;
901         QUERYDB(out.str(),q);
902         
903         
904         while (!q.eof())
905           {
906             for (int fld = 0; fld < q.numFields(); fld++)
907               {
908                           results<<q.getStringField(fld);
909                           if(searchParam=="")
910                           {
911                                   results<<"#";
912                           }
913               }
914             q.nextRow();
915           }
916         result=results.str();
917       
918   }
919   //===================================================================== 
920   unsigned int SQLiteTreeHandler::GetNumberOfChildren(tree::Node* n) 
921   { 
922     // Query DB
923     int nb=0;
924     int level = n->GetLevel();
925
926     if(level<GetTree().GetNumberOfLevels()&& level>0)
927       {
928         std::string query = "SELECT NumberOfChildren FROM ";
929         query += GetTree().GetLevelDescriptor(level).GetName();
930         if (level>0)
931           {
932             query += " WHERE ID='" + n->GetAttribute("ID") 
933               + "'";
934           }
935         CppSQLite3Query q;
936         QUERYDB(query,q);
937         
938         
939         while (!q.eof())
940           {
941             for (int fld = 0; fld < q.numFields(); fld++)
942               {
943                 nb=q.getIntField(fld);  
944               }
945             q.nextRow();
946           }
947       }
948     /*
949     if(nb==0)
950       { 
951         nb=1;
952       }
953     */
954     return nb; 
955   }
956
957   //===================================================================== 
958   void SQLiteTreeHandler::GetTopLevelNodeId(const std::string& searchParam, const std::string& searchValue, std::string& parent_id) 
959   {
960           int level=GetTree().GetNumberOfLevels()-1;
961           std::string sp=searchParam.c_str();
962           std::string sv=searchValue.c_str();
963
964           while(level>1)
965           {
966                 std::stringstream out;
967                 std::stringstream results;
968                 out<<"SELECT PARENT_ID FROM "<<GetTree().GetLevelDescriptor(level).GetName();
969                 out<<" WHERE "<<sp<<"='"<<sv<<"'";      
970                 CppSQLite3Query q;
971                 QUERYDB(out.str(),q);
972                 
973                 
974                 while (!q.eof())
975                 {
976                         for (int fld = 0; fld < q.numFields(); fld++)
977                         {
978                                 results<<q.getStringField(fld);
979                         }
980                         q.nextRow();
981                 }
982                 level=level-1;
983                 sp="ID";
984                 sv=results.str();
985           }
986           parent_id=sv;
987
988   }
989
990   //=====================================================================
991   void SQLiteTreeHandler::RemoveEntries(const std::string i_table, 
992                 const std::string i_attribute, 
993                 const std::string i_operand, 
994                 const std::string i_val)
995     {
996         std::stringstream query;
997                 query<<"DELETE  FROM "<<i_table<<" WHERE "<<i_attribute<<" "<<i_operand<<" '"<<i_val<<"'";
998         UPDATEDB(query.str());
999         }
1000
1001         //=====================================================================
1002   void SQLiteTreeHandler::BeginTransaction()
1003     {
1004                 std::stringstream out;
1005                 out<<"begin transaction;";
1006         UPDATEDB(out.str());
1007         }
1008
1009         //=====================================================================
1010   void SQLiteTreeHandler::EndTransaction()
1011     {
1012        std::stringstream out;
1013                 out<<"commit transaction;";
1014         UPDATEDB(out.str());
1015         }
1016
1017 } // namespace creaImageIO