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