]> Creatis software - creaImageIO.git/blob - src2/creaImageIOSQLiteTreeHandler.cpp
3531408532557debd0325133ae74ae7a9435b275
[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   std::string& SQLformat(std::string& str)
537   {
538     // quote must be doubled
539     boost::algorithm::replace_all(str,"'","''");
540     // Found strange strings which contained NULL char INSIDE string 
541     int i,size=str.size();
542     for (i=0;i<size;++i) 
543       {
544         if (str[i]==0) 
545           {
546             str = str.substr(0,i);
547             break;
548           }
549       }
550     //    if (i<str.size())
551     return 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     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         values += "'" + SQLformat(i->second) + "'"; 
574         atts += ",";
575         values += ",";
576         GimmickMessage(4,"'"<<i->first<<"' = '"<<i->second<<"'"<<std::endl);
577       }
578     atts[atts.size()-1]=' ';
579     values[values.size()-1]=' ';
580
581     str = "("+atts+") VALUES ("+values+")";
582     GimmickMessage(4,"Result = '"<<str<<"'"<<std::endl);
583   }
584   //=====================================================================
585
586   //=====================================================================
587   tree::Node* SQLiteTreeHandler::DBGetParent( const AttributeMapType& attr) 
588   {
589     Node* parent = GetTree().GetTree();
590     bool go_down;
591     do 
592       {
593         go_down = false;
594         // Load the children of the current parent
595         DBLoadChildren(parent);
596         // Iterate the children 
597         tree::Node::ChildrenListType::const_iterator i;
598         for (i = parent->GetChildrenList().begin();
599              i!= parent->GetChildrenList().end();
600              ++i)
601           {
602             if ( (*i)->Matches( attr ) ) 
603               {
604                 go_down = true;
605                 parent = *i;
606                 break;
607               }
608           }     
609       }
610     while (go_down);
611     return parent;
612   }
613   //=====================================================================
614
615   //=====================================================================
616   int SQLiteTreeHandler::DBLoadChildren(tree::Node* node, 
617                                         int numberoflevels)
618   {
619     if (node->GetLevel()+1 >= node->GetTree()->GetNumberOfLevels() ) 
620       return 0;
621
622     GimmickMessage(2,"Loading children of '"<<node->GetLabel()
623                    <<"'"<<std::endl);
624
625     int nbloaded = 0;
626     // If children loaded we do not have to do it but we need to recurse
627     // in order to load the children's children if necessary, and so on...
628     if (node->GetChildrenLoaded()) 
629       {
630         // Iterate the children 
631
632         tree::Node::ChildrenListType::iterator i;
633         for (i = node->GetChildrenList().begin();
634              i!= node->GetChildrenList().end();
635              ++i)
636           {
637             nbloaded += DBLoadChildren(*i,numberoflevels-1);
638           }
639         node->SetChildrenLoaded(true);
640         return nbloaded;
641
642       }
643         else
644         {
645     /// If children not loaded : do it and recurse
646
647     // Query DB
648     int level = node->GetLevel();
649     std::string query = "SELECT * FROM ";
650         
651     query += GetTree().GetLevelDescriptor(level+1).GetName();
652     if (level>0)
653       {
654         query += " WHERE PARENT_ID='" + node->GetAttribute("ID") 
655           + "'";
656       }
657     CppSQLite3Query q;
658     QUERYDB(query,q);
659
660         int p=0;
661     while (!q.eof())
662       {
663
664         //      std::cout << "DBLoadCh : creating node level "<<level+1<<std::endl;
665
666         nbloaded++;
667         Node* n = new Node(node);
668         for (int fld = 0; fld < q.numFields(); fld++)
669           {
670             n->UnsafeSetAttribute(q.fieldName(fld),q.getStringField(fld));          
671           }
672
673         // recurse 
674         if ( numberoflevels != 1 ) 
675           {
676             //  msw[2].Pause();
677             nbloaded += DBLoadChildren(n, numberoflevels-1);
678             //      msw[2].Resume();
679           }
680         // next entry in db
681         q.nextRow();
682       }
683
684     node->SetChildrenLoaded(true);
685         
686     
687     //    msw[2].Pause();
688     return nbloaded;
689         }
690   }
691   //=====================================================================
692
693   //======================================================================
694   void SQLiteTreeHandler::DBInsert(tree::Node* n)
695   {
696     GimmickMessage(2,"Inserting in DB '"<<n->GetLabel()
697                    <<"'"<<std::endl);
698     std::string val;
699     SQLAppendAttributesValues(n,val);
700     std::string insert("INSERT INTO ");
701     insert += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
702     insert += " " + val + ";";
703
704     UPDATEDB(insert);
705         
706     // Store DB id of newly created node;
707     long lastrow = mDB->lastRowId();
708     std::stringstream ri;
709     ri << mDB->lastRowId();
710     n->SetAttribute("ID",ri.str());
711   }
712   //======================================================================
713
714   //======================================================================
715   /// Graft the branch defined by the attributes to the parent
716   void SQLiteTreeHandler::DBGraftToParent( tree::Node* parent, 
717                                             const AttributeMapType& attr)
718   {
719     //    std::cout <<"Grafting to parent '"<<parent->GetLabel()
720     //             <<"'"<<std::endl;
721
722     for (int level = parent->GetLevel()+1;
723          level < GetTree().GetNumberOfLevels();
724          level++)
725       {
726         // Create Node
727         tree::Node* child = new tree::Node(parent,attr);
728         child->SetChildrenLoaded(true);
729         if (level>1)
730           {
731             int nc = GetNumberOfChildren(parent)+1;
732             
733             //  std::cout<<"Number of children "<<parent->GetNumberOfChildren()<<std::endl;
734             std::stringstream out;
735             out << nc;
736             SetAttribute(parent,"NumberOfChildren",out.str());
737           }
738
739         // Set PARENT_ID if necessary 
740         if ( parent->GetLevel()>0 )
741           child->SetAttribute("PARENT_ID",parent->GetAttribute("ID"));
742         
743         // Insert in DB
744         DBInsert(child);
745         
746         // Down one level
747         parent = child;
748           }
749   }
750   //======================================================================
751
752
753   //===================================================================== 
754   /// Sets an attribute of a Node
755   bool SQLiteTreeHandler::DBSetAttribute(tree::Node* n, 
756                                          const std::string& key,
757                                          const std::string& value)
758   {
759     GimmickMessage(3,"Setting Attribute of '"<<n->GetLabel()<<
760                    "' "<<key<<"='"<<value<<"'"<<std::endl);
761
762     n->SetAttribute(key,value);
763     std::string sql = "UPDATE ";
764     sql += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
765     sql += " SET ";
766     sql += key;
767     sql += " = '";
768     sql += value;
769     sql += "' WHERE ID = '";
770     sql += n->GetAttribute("ID");
771         sql +="'";
772     //    sql += " LIMIT 1";
773     UPDATEDB(sql);
774         return true;
775   }
776
777   //===================================================================== 
778   /// Sets an attribute of a Node
779   void SQLiteTreeHandler::DBSetAttribute(const std::string& levelDescriptor, 
780                               const std::string& key,
781                               const std::string& value,
782                                   const std::string& searchParam, 
783                                   const std::string& searchVal)
784   {
785
786     std::string sql = "UPDATE ";
787     sql += levelDescriptor;
788     sql += " SET ";
789     sql += key;
790     sql += " = '";
791     sql += value;
792     sql += "' WHERE ";
793         sql += searchParam;
794         sql += " = '";
795     sql += searchVal;
796         sql += "'";
797         std::cout<<sql<<std::endl;
798     UPDATEDB(sql);
799   }
800    //=====================================================================
801   void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node)
802   {
803        
804     std::string query = "DELETE FROM ";
805    
806
807         query += GetTree().GetLevelDescriptor(node->GetLevel()).GetName();
808         
809     query += " WHERE ID='"+ node->GetAttribute("ID") + "';";
810  
811     UPDATEDB(query);
812         GimmickDebugMessage(2,
813                             " Deleting '"
814                                 <<node->GetLabel()<<"' with ID '"
815                             <<node->GetAttribute("ID")
816                             <<"' in level "<< GetTree().GetLevelDescriptor(node->GetLevel()).GetName()
817                             <<std::endl);
818
819
820         if(node->GetNumberOfChildren()!=0)
821         {
822                 Node::ChildrenListType::iterator i;
823                 for (i  = node->GetChildrenList().begin();
824                 i != node->GetChildrenList().end();
825                 i++)
826                 {
827                 DBRecursiveRemoveNode((*i));
828                 }
829         }
830         else if(node->GetLevel()<GetTree().GetNumberOfLevels()-1)
831         {
832                 DBRecursiveRemoveNode(node->GetLevel()+1,node->GetAttribute("ID"));
833     }
834   }
835
836   //=====================================================================
837   void SQLiteTreeHandler::DBRecursiveRemoveNode(int level, std::string parentId)
838   {
839     std::stringstream out;
840         std::stringstream result;
841         out<<"SELECT ID FROM "<<GetTree().GetLevelDescriptor(level).GetName()<<" WHERE PARENT_ID='"<<parentId<<"'";
842                 
843         CppSQLite3Query q;
844         QUERYDB(out.str(),q);
845         
846         while (!q.eof())
847           {
848             for (int fld = 0; fld < q.numFields(); fld++)
849               {
850                           result<<q.getStringField(fld)<<"#";
851               }
852             q.nextRow();
853           }
854           std::string res=result.str();
855           size_t ini=0;
856           size_t fin=0;
857           while(fin<res.size()-1)
858           {
859            fin=res.find('#',ini);
860            DBDelete(GetTree().GetLevelDescriptor(level).GetName(),"ID",res.substr(ini,fin-ini));
861           if(level<GetTree().GetNumberOfLevels()-1)
862           {
863                 DBRecursiveRemoveNode(level+1,res.substr(ini,fin-ini));
864           } 
865            ini=fin+1;
866           }
867           
868     
869   }
870
871   //=====================================================================
872   void SQLiteTreeHandler::DBDelete(std::string levelDescriptor, std::string key, std::string value)
873   {
874        
875     std::stringstream query;
876         query<<"DELETE FROM "<<levelDescriptor<<" WHERE "<<key<<"='"<<value<<"';";
877  
878     UPDATEDB(query.str());
879         GimmickDebugMessage(2," Deleting: Query: "<<query.str()<<std::endl);
880   }
881
882
883   //===================================================================== 
884   void SQLiteTreeHandler::GetAttribute(std::string levelDescriptor,
885                                                                            std::string searchParam, 
886                                                                            std::string searchVal, 
887                                                                            std::string key, 
888                                                                            std::string& result) 
889   { 
890         std::stringstream out;
891         std::stringstream results;
892         out<<"SELECT "<<key<<" FROM "<<levelDescriptor;
893         if(searchParam!="")
894         {
895                 out<<" WHERE "<<searchParam<<"='"<<searchVal<<"'";
896         }
897         
898         CppSQLite3Query q;
899         QUERYDB(out.str(),q);
900         
901         
902         while (!q.eof())
903           {
904             for (int fld = 0; fld < q.numFields(); fld++)
905               {
906                           results<<q.getStringField(fld);
907                           if(searchParam=="")
908                           {
909                                   results<<"#";
910                           }
911               }
912             q.nextRow();
913           }
914         result=results.str();
915       
916   }
917   //===================================================================== 
918   unsigned int SQLiteTreeHandler::GetNumberOfChildren(tree::Node* n) 
919   { 
920     // Query DB
921     int nb=0;
922     int level = n->GetLevel();
923
924     if(level<GetTree().GetNumberOfLevels()&& level>0)
925       {
926         std::string query = "SELECT NumberOfChildren FROM ";
927         query += GetTree().GetLevelDescriptor(level).GetName();
928         if (level>0)
929           {
930             query += " WHERE ID='" + n->GetAttribute("ID") 
931               + "'";
932           }
933         CppSQLite3Query q;
934         QUERYDB(query,q);
935         
936         
937         while (!q.eof())
938           {
939             for (int fld = 0; fld < q.numFields(); fld++)
940               {
941                 nb=q.getIntField(fld);  
942               }
943             q.nextRow();
944           }
945       }
946     /*
947     if(nb==0)
948       { 
949         nb=1;
950       }
951     */
952     return nb; 
953   }
954
955   //===================================================================== 
956   void SQLiteTreeHandler::GetTopLevelNodeId(const std::string& searchParam, const std::string& searchValue, std::string& parent_id) 
957   {
958           int level=GetTree().GetNumberOfLevels()-1;
959           std::string sp=searchParam.c_str();
960           std::string sv=searchValue.c_str();
961
962           while(level>1)
963           {
964                 std::stringstream out;
965                 std::stringstream results;
966                 out<<"SELECT PARENT_ID FROM "<<GetTree().GetLevelDescriptor(level).GetName();
967                 out<<" WHERE "<<sp<<"='"<<sv<<"'";      
968                 CppSQLite3Query q;
969                 QUERYDB(out.str(),q);
970                 
971                 
972                 while (!q.eof())
973                 {
974                         for (int fld = 0; fld < q.numFields(); fld++)
975                         {
976                                 results<<q.getStringField(fld);
977                         }
978                         q.nextRow();
979                 }
980                 level=level-1;
981                 sp="ID";
982                 sv=results.str();
983           }
984           parent_id=sv;
985
986   }
987
988   //=====================================================================
989   void SQLiteTreeHandler::RemoveEntries(const std::string i_table, 
990                 const std::string i_attribute, 
991                 const std::string i_operand, 
992                 const std::string i_val)
993     {
994         std::stringstream query;
995                 query<<"DELETE  FROM "<<i_table<<" WHERE "<<i_attribute<<" "<<i_operand<<" '"<<i_val<<"'";
996         UPDATEDB(query.str());
997         }
998
999         //=====================================================================
1000   void SQLiteTreeHandler::BeginTransaction()
1001     {
1002                 std::stringstream out;
1003                 out<<"begin transaction;";
1004         UPDATEDB(out.str());
1005         }
1006
1007         //=====================================================================
1008   void SQLiteTreeHandler::EndTransaction()
1009     {
1010        std::stringstream out;
1011                 out<<"commit transaction;";
1012         UPDATEDB(out.str());
1013         }
1014
1015 } // namespace creaImageIO