]> Creatis software - creaImageIO.git/blob - src2/creaImageIOSQLiteTreeHandler.cpp
3d3fe70c1639ad2357a75f628ff63462020a2e9f
[creaImageIO.git] / src2 / creaImageIOSQLiteTreeHandler.cpp
1 #include <creaImageIOSQLiteTreeHandler.h>
2 #include <creaImageIOSystem.h>
3
4 #include "CppSQLite3.h"
5
6 #include <sys/stat.h>
7
8 //#include <creaImageIOSQLiteTreeHandlerStructure.h>
9
10 //#include <creaImageIOUtilities.h>
11
12 //#include <icons/database.xpm>
13
14 #include <deque>
15
16 //#include <icons/close.xpm>
17
18 #include <creaWx.h>
19 using namespace crea;
20
21 #include <boost/filesystem.hpp>
22 #include <boost/algorithm/string/replace.hpp>
23
24 namespace creaImageIO
25 {
26   using namespace tree;
27
28
29   //=============================================================
30   SQLiteTreeHandler::SQLiteTreeHandler(const std::string& filename)
31     : mFileName(filename)
32   {
33     mDB = new CppSQLite3DB;
34         mIsAdding=false;
35     GimmickMessage(1,"SQLite version : "
36                    <<std::string(mDB->SQLiteVersion())<< std::endl);
37   }
38   //=============================================================
39
40   //=============================================================
41   SQLiteTreeHandler::~SQLiteTreeHandler()
42   {
43     delete mDB;
44   }
45   //=============================================================
46   
47
48   //=============================================================
49   //  void SQLiteTreeHandler::Print() const 
50   //  {
51     /*
52     std::cout << "-> '"<<GetName()<< "' - '"
53               << GetFileName()<<"'"<<std::endl;
54     ChildrenListType::const_iterator i;
55     for (i=GetChildrenList().begin(); i!=GetChildrenList().end(); i++)
56       {
57         (*i)->Print();
58       }
59     */
60   //  }
61   //=============================================================
62   
63   //=====================================================================
64   /*
65   bool SQLiteTreeHandler::LocationIsValid()
66   {
67     // TO DO 
68     return true;
69   }
70   */
71   //=====================================================================
72
73
74   //=====================================================================
75   bool SQLiteTreeHandler::Open(bool writable)
76   {
77     //    std::cout << "***> SQLiteTreeHandler::Open('"<<GetFileName()<<"')"<<std::endl;
78     SetWritable(writable);
79     return DBOpen();
80   }
81
82   //=====================================================================
83   bool SQLiteTreeHandler::Create(bool writable)
84   {
85     //    std::cout << "***> SQLiteTreeHandler::New('"<<GetFileName()<<"')"<<std::endl;
86     SetWritable(writable);
87     return DBCreate();
88   }
89   //=====================================================================
90
91
92   //=====================================================================
93   bool SQLiteTreeHandler::Close()
94   {
95     return true;
96   }
97   //=====================================================================
98
99
100   //=====================================================================
101   bool SQLiteTreeHandler::Destroy()
102   {
103     return false;
104   }
105   
106   //===================================================================== 
107
108   //===================================================================== 
109   int SQLiteTreeHandler::LoadChildren(tree::Node* parent, int maxlevel)
110   {
111     if (parent==0) parent = GetTree().GetTree();
112     return DBLoadChildren(parent,maxlevel);
113   }
114   //===================================================================== 
115
116
117
118
119   //===================================================================== 
120   void SQLiteTreeHandler::UnLoad(tree::Node* n)
121   {
122   }
123   //===================================================================== 
124
125   //===================================================================== 
126   int SQLiteTreeHandler::AddBranch( const AttributeMapType& attr )
127   {
128     tree::Node* parent = DBGetParent(attr);
129     DBGraftToParent(parent,attr);
130     return (parent->GetLevel()+1);
131           
132   }
133   //===================================================================== 
134  
135
136   //===================================================================== 
137    bool SQLiteTreeHandler::Remove(tree::Node* node)
138    {
139    DBRecursiveRemoveNode(node);
140  
141     //    std::cout << "DELETE"<<std::endl;
142    bool remove=false;
143    tree::Node* parent=node->GetParent();
144     if (parent)
145       {
146         int nC = parent->RemoveChildrenFromList(node);
147         if(nC>0 && parent->GetLevel()>0)
148         {       
149                 std::stringstream out;
150                 out <<nC;
151                 SetAttribute(parent,"NumberOfChildren",out.str());
152         }
153         else
154         {
155                 remove=true;
156         }
157
158       }
159     delete node;
160         if(remove&&parent->GetLevel()>0)
161         {
162                 Remove(parent);
163         }
164     //    std::cout << "DELETE OK"<<std::endl;
165     return true;
166    }
167   
168   //===================================================================== 
169
170   //===================================================================== 
171   /// Sets an attribute of a Node
172   bool SQLiteTreeHandler::SetAttribute(tree::Node* n, 
173                                        const std::string& key,
174                                        const std::string& value)
175   {
176     if (n==0) n=GetTree().GetTree();
177     return DBSetAttribute(n,key,value);
178   }
179   //===================================================================== 
180    //===================================================================== 
181   /// Sets an attribute
182   void SQLiteTreeHandler::SetAttribute(const std::string& levelDescriptor, 
183                               const std::string& key,
184                               const std::string& value,
185                                   const std::string& searchParam, 
186                                   const std::string& searchVal)
187   {
188         DBSetAttribute(levelDescriptor,key,value,searchParam, searchVal);
189   }
190   //===================================================================== 
191   /// Deletes a tuple
192   void SQLiteTreeHandler::DeleteTuple(std::string levelDescriptor, 
193                                                                 std::string key, std::string value)
194   {
195     DBDelete(levelDescriptor,key,value);
196   }
197   //===================================================================== 
198
199
200
201
202
203
204
205
206
207
208
209
210
211   //=====================================================================
212   // SQLite DB specific methods
213   //=====================================================================
214
215
216
217
218   //=====================================================================
219   char* format_sql(const std::string& s)
220   { 
221     return sqlite3_mprintf("%q",s.c_str());
222   }
223   //=====================================================================
224
225   //  sqlite3_exec(db, zSQL, 0, 0, 0);
226   //  sqlite3_free(zSQL);
227   //    char* CHAIN = format_sql(QUER);         \
228 //  sqlite3_free(CHAIN);                                \
229
230   //=====================================================================
231 #define QUERYDB(QUER,RES)                                               \
232     try                                                                 \
233       {                                                                 \
234         GimmickMessage(2,"SQL query: '"<<QUER<<"'"<<std::endl);         \
235         RES = mDB->execQuery(QUER.c_str());                             \
236       }                                                                 \
237     catch (CppSQLite3Exception& e)                                      \
238       {                                                                 \
239         GimmickError("SQLite query '"<<QUER<<"' : "                     \
240                      << e.errorCode() << ":"                            \
241                      << e.errorMessage() );                             \
242       }                                                                 \
243     
244   //=====================================================================
245   
246   //=====================================================================
247 #define UPDATEDB(UP)                                                    \
248   try                                                                   \
249     {                                                                   \
250       GimmickMessage(2,"SQL update: '"<<UP<<"'"<<std::endl);            \
251       mDB->execDML(UP.c_str());                                         \
252     }                                                                   \
253   catch (CppSQLite3Exception& e)                                        \
254     {                                                                   \
255       GimmickError("SQLite update '"<<UP<<"' Error : "                  \
256                    << e.errorCode() << ":"                              \
257                    << e.errorMessage() );                               \
258     }                                                                   
259   //=====================================================================
260
261
262   //=====================================================================
263   bool SQLiteTreeHandler::DBOpen()
264   {
265     GimmickMessage(1,"Opening SQLite database '"<<GetFileName()
266                    <<"' ... "<<std::endl);
267     // OPENING FILE
268     if (!boost::filesystem::exists(GetFileName())) 
269       {
270         return false;
271       }
272
273     try
274       {
275         mDB->open(GetFileName().c_str());
276       }
277     catch (CppSQLite3Exception& e)
278       {
279         GimmickError("Opening '"<<GetFileName()<<"' : "
280                      << e.errorCode() << ":" 
281                      << e.errorMessage());
282         return false;
283       }
284     // IMPORT TREE DESCRIPTION (AND TEST DB VALIDITY)
285     if (!DBImportTreeDescription())
286       {
287         return false;
288       }
289
290     GimmickDebugMessage(1,"Opening SQLite database '"<<GetFileName()
291                    <<"' ... OK"<<std::endl);
292     return true;
293   }
294   //=====================================================================
295
296   //=====================================================================
297   bool SQLiteTreeHandler::DBCreate()
298   {
299     GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
300                    <<"' ... "<<std::endl);
301
302     if (boost::filesystem::exists(GetFileName())) 
303       {
304         GimmickError(GetFileName()<<"' : "
305                      << "file already exists");
306         return false;
307       }
308     
309     // OPENING
310     try
311       {
312         mDB->open(GetFileName().c_str());
313       }
314     catch (CppSQLite3Exception& e)
315       {
316         GimmickError(e.errorCode() << ":" 
317                      << e.errorMessage() <<std::endl);
318         return false;
319       }
320     
321      
322     // CREATING TABLES
323     
324     std::string command;
325     // Create LEVELS table
326     command = "create table LEVELS\n";
327     command += "( Name text )\n";
328     UPDATEDB(command);
329     int l;
330     // Iterate the Levels
331     for (l=0; l<GetTree().GetNumberOfLevels(); l++)
332       {
333         command = "INSERT INTO LEVELS (Name) VALUES ('";
334         command += GetTree().GetLevelDescriptor(l).GetName();
335         command += "')";
336         UPDATEDB(command);
337         
338         // Create table of level (for level>0, i.e. not Root)
339         if (l>=0)
340           {
341             command = "CREATE TABLE ";
342             command += GetTree().GetLevelDescriptor(l).GetName();
343             command += "\n(\nID INTEGER PRIMARY KEY";
344             if (l>1) 
345               {
346                 command += ",\nPARENT_ID int not null"; 
347               }
348             SQLAppendAttributesDefinition(l,command);
349             if (l>1) 
350               {
351                 command += ",\nconstraint FK_PARENT foreign key (PARENT_ID) references ";
352                 command += GetTree().GetLevelDescriptor(l-1).GetName();
353                 command += "(ID) on delete restrict on update restrict";
354               }
355             command += "\n)";
356             UPDATEDB(command);
357             
358             
359             // Add Attribute 'ID' to Description
360             GetTree().GetDescriptor().Add
361               (AttributeDescriptor( "ID",
362                                     "Database Identifier",
363                                     0,0,
364                                     AttributeDescriptor::PRIVATE
365                                     ),l);
366             
367             if (l>1) 
368               {
369                 // Add Attribute 'PARENT_ID' to Description
370                 GetTree().GetDescriptor().Add
371                   (AttributeDescriptor( "PARENT_ID",
372                                         "Database Parent Identifier",
373                                         0,0,
374                                         AttributeDescriptor::PRIVATE
375                                         ),l);
376               }
377             
378           }
379         
380         // Create table *_ATTRIBUTES
381         
382         command = "CREATE TABLE ";
383         command += GetTree().GetLevelDescriptor(l).GetName();
384         command += "_Attributes\n(\n";
385         command += "Key text,\n";
386         command += "Name text,\n";          
387         command += "DicomGroup int,\n";
388         command += "DicomElement int,\n";           
389         command += "Flags int\n";           
390         command += "\n)";
391         UPDATEDB(command);
392         
393         
394         // Fill the table *_ATTRIBUTES
395         LevelDescriptor::AttributeDescriptorListType::const_iterator i;
396         for (i  = GetTree().GetAttributeDescriptorList(l).begin();
397              i != GetTree().GetAttributeDescriptorList(l).end();
398              ++i)
399           {
400             
401             std::stringstream insert;
402             insert << "INSERT INTO "
403                    << GetTree().GetLevelDescriptor(l).GetName()
404                    << "_Attributes (Key,Name,DicomGroup,DicomElement,Flags) "
405                    << "VALUES ('"
406                    << i->GetKey() << "','"
407                    << i->GetName() << "',"
408                    << i->GetGroup() << ","
409                    << i->GetElement() << ","
410                    << i->GetFlags() << ");";
411             UPDATEDB(insert.str());
412           }
413
414       } // For l=0...
415
416     // Initialize the root attributes
417     GetTree().InitializeAttributeMap();
418     // Insert the root in the level 0 table 
419     DBInsert(GetTree().GetTree());
420     
421     
422     GetTree().SetChildrenLoaded(true);
423     GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
424                    <<"' ... OK"<<std::endl);
425     return true;
426   }
427   //=====================================================================
428   
429   //=====================================================================
430   void SQLiteTreeHandler::SQLAppendAttributesDefinition(int level,
431                                                         std::string& s)
432   {
433     LevelDescriptor::AttributeDescriptorListType::const_iterator i;
434     for (i  = GetTree().GetAttributeDescriptorList(level).begin();
435          i != GetTree().GetAttributeDescriptorList(level).end();
436          ++i)
437       {
438         //      if (i->second.flags==1) continue;
439         s += ",\n";
440         s += i->GetKey();
441         s += " text";
442       }
443   }
444   //=====================================================================
445   
446   
447   //=====================================================================
448   bool SQLiteTreeHandler::DBImportTreeDescription()
449   {
450     GimmickMessage(1,"Importing tree description from database ..."
451                    <<std::endl);
452
453     // Test table 'LEVELS' existence
454     if ( ! mDB->tableExists("LEVELS") )
455       {
456         GimmickMessage(1,"!! ERROR : Table 'LEVELS' does not exist"
457                        <<std::endl);
458         return false;
459       }
460
461     tree::Descriptor& desc = GetTree().GetDescriptor();
462     // clears the existing one
463     desc.Clear();
464      
465     int nblevel = 0;
466     std::string query = "SELECT * FROM LEVELS";
467     CppSQLite3Query q;
468     QUERYDB(query,q);
469
470     while (!q.eof())
471       {
472         std::string name = q.getStringField(0);
473         GimmickMessage(2," * Importing level '"<<name<<"'"<<std::endl);
474         desc.Add(LevelDescriptor(name));
475         nblevel++;
476         q.nextRow();
477       }   
478     
479     for (int level = 0; level < nblevel; ++level )
480       {
481         std::string table = GetTree().GetLevelDescriptor(level).GetName();
482         table += "_Attributes";
483         // Test table 'LEVELS' existence
484         if ( ! mDB->tableExists(table.c_str()) )
485           {
486             GimmickMessage(1,"!! ERROR : Table '"<<table<<"' does not exist"
487                            <<std::endl);
488             return false;
489           }
490         
491         std::string query = "SELECT * FROM ";
492         query += table;
493         CppSQLite3Query q;
494         QUERYDB(query,q);
495         
496         GimmickMessage(2," * Level '"
497                        <<GetTree().GetLevelDescriptor(level).GetName()
498                        <<"'"<<std::endl);
499
500         // Test that ID and PARENT_ID mandatory attributes exist
501         bool ID_found = false;
502         bool PARENT_ID_found = false;
503         if (level==0) ID_found = true;
504         if (level<=1) PARENT_ID_found = true;
505
506         while (!q.eof())
507           {
508             std::string key(q.getStringField(0));
509             std::string name(q.getStringField(1));
510             GimmickMessage(2,"  - Importing attribute '"<<key<<"' '"<<name
511                            <<"'"<<std::endl);
512             desc.Add
513               (AttributeDescriptor( key, // Key
514                                     name, // Name
515                                     q.getIntField(2), // Group
516                                     q.getIntField(3), // Element 
517                                     q.getIntField(4) // Flags
518                                     ),level);
519             if ( key == "ID" ) 
520               {
521                 ID_found = true;
522               }
523             if ( key == "PARENT_ID" ) 
524               {
525                 PARENT_ID_found = true;
526               }
527             q.nextRow();
528           }
529         
530         if ( ! (ID_found || PARENT_ID_found ) )
531           {
532             GimmickMessage(1,"!! ERROR : Table '"<<table
533                            <<"' does not contain mandatory attribute ID or PARENT_ID"
534                            <<std::endl);
535             return false;
536  
537           }
538       }
539
540
541     // Create the attributes table for Root (i.e. Tree)
542     LevelDescriptor::AttributeDescriptorListType::const_iterator a;
543     for (a = GetTree().GetAttributeDescriptorList(0).begin();
544          a!= GetTree().GetAttributeDescriptorList(0).end();
545          ++a)
546       {
547         /*
548         std::string v;
549         AttributeMapType::const_iterator i = attr.find(a->GetKey());
550         if ( i != attr.end() )  
551           {
552             v = i->second;
553           }
554         */
555         GetTree().UnsafeSetAttribute( a->GetKey(), "" );
556       }
557
558     // Reading Root attributes
559     // Query DB
560     query = "SELECT * FROM ";
561     query += GetTree().GetLevelDescriptor(0).GetName();
562     QUERYDB(query,q);
563
564     for (int fld = 0; fld < q.numFields(); fld++)
565       {
566         GetTree().UnsafeSetAttribute(q.fieldName(fld),
567                                      q.getStringField(fld));        
568       }
569
570     GimmickMessage(1,"Importing tree description from database ... OK"
571                    <<std::endl);
572     return true;
573   }
574   //=====================================================================
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592   //========================================================================
593   /// 
594   std::string& SQLformat(std::string& str)
595   {
596     // quote must be doubled
597     boost::algorithm::replace_all(str,"'","''");
598     // Found strange strings which contained NULL char INSIDE string 
599     int i,size=str.size();
600     for (i=0;i<size;++i) 
601       {
602         if (str[i]==0) 
603           {
604             str = str.substr(0,i);
605             break;
606           }
607       }
608     //    if (i<str.size())
609     return str;
610   }
611   //========================================================================
612   
613   //=====================================================================
614   void SQLiteTreeHandler::SQLAppendAttributesValues(tree::Node* n, 
615                                                     std::string& str)
616   {
617     GimmickMessage(4,"SQLAppendAttributesValues"<<std::endl);
618     std::string atts="";
619     std::string values="";
620     tree::Node::AttributeMapType::iterator i;
621     for (i =  n->GetAttributeMap().begin();
622          i != n->GetAttributeMap().end();
623          i++)
624       {
625         if (i->first=="ID") 
626           {
627             continue;
628           }
629         //      std::cout << "("<<i->first<<","<<i->second<<")"<<std::endl;
630         atts += "'" + i->first + "'";
631         values += "'" + SQLformat(i->second) + "'"; 
632         atts += ",";
633         values += ",";
634         GimmickMessage(4,"'"<<i->first<<"' = '"<<i->second<<"'"<<std::endl);
635       }
636     atts[atts.size()-1]=' ';
637     values[values.size()-1]=' ';
638
639     str = "("+atts+") VALUES ("+values+")";
640     GimmickMessage(4,"Result = '"<<str<<"'"<<std::endl);
641   }
642   //=====================================================================
643
644   //=====================================================================
645   tree::Node* SQLiteTreeHandler::DBGetParent( const AttributeMapType& attr) 
646   {
647     Node* parent = GetTree().GetTree();
648     bool go_down;
649     do 
650       {
651         go_down = false;
652         // Load the children of the current parent
653         DBLoadChildren(parent);
654         // Iterate the children 
655         tree::Node::ChildrenListType::const_iterator i;
656         for (i = parent->GetChildrenList().begin();
657              i!= parent->GetChildrenList().end();
658              ++i)
659           {
660             if ( (*i)->Matches( attr ) ) 
661               {
662                 go_down = true;
663                 parent = *i;
664                 break;
665               }
666           }     
667       }
668     while (go_down);
669     return parent;
670   }
671   //=====================================================================
672
673
674   //=====================================================================
675   int SQLiteTreeHandler::DBLoadChildren(tree::Node* node, 
676                                         int numberoflevels)
677   {
678     if (node->GetLevel()+1 >= node->GetTree()->GetNumberOfLevels() ) 
679       return 0;
680
681     GimmickMessage(2,"Loading children of '"<<node->GetLabel()
682                    <<"'"<<std::endl);
683
684     int nbloaded = 0;
685     // If children loaded we do not have to do it but we need to recurse
686     // in order to load the children's children if necessary, and so on...
687     if (node->GetChildrenLoaded()) 
688       {
689         // Iterate the children 
690
691         tree::Node::ChildrenListType::iterator i;
692         for (i = node->GetChildrenList().begin();
693              i!= node->GetChildrenList().end();
694              ++i)
695           {
696             nbloaded += DBLoadChildren(*i,numberoflevels-1);
697           }
698         node->SetChildrenLoaded(true);
699         return nbloaded;
700
701       }
702         else
703         {
704     /// If children not loaded : do it and recurse
705
706     // Query DB
707     int level = node->GetLevel();
708     std::string query = "SELECT * FROM ";
709         
710     query += GetTree().GetLevelDescriptor(level+1).GetName();
711     if (level>0)
712       {
713         query += " WHERE PARENT_ID='" + node->UnsafeGetAttribute("ID") 
714           + "'";
715       }
716     CppSQLite3Query q;
717     QUERYDB(query,q);
718
719         int p=0;
720     while (!q.eof())
721       {
722
723         //      std::cout << "DBLoadCh : creating node level "<<level+1<<std::endl;
724
725         nbloaded++;
726         Node* n = new Node(node);
727         for (int fld = 0; fld < q.numFields(); fld++)
728           {
729             n->UnsafeSetAttribute(q.fieldName(fld),q.getStringField(fld));          
730           }
731         /*
732         // Index 
733         TypeId ti;
734         ti.type = type;
735         ti.id = n->GetFieldValue("ID");    
736         mTypeIdToNodeMap[ti] = n;
737         */
738         // recurse 
739         if ( numberoflevels != 1 ) 
740           {
741             //  msw[2].Pause();
742             nbloaded += DBLoadChildren(n, numberoflevels-1);
743             //      msw[2].Resume();
744           }
745         // next entry in db
746         q.nextRow();
747       }
748
749     node->SetChildrenLoaded(true);
750         
751     
752     //    msw[2].Pause();
753     return nbloaded;
754         }
755   }
756   //=====================================================================
757
758   //======================================================================
759   void SQLiteTreeHandler::DBInsert(tree::Node* n)
760   {
761     GimmickMessage(2,"Inserting in DB '"<<n->GetLabel()
762                    <<"'"<<std::endl);
763     std::string val;
764     SQLAppendAttributesValues(n,val);
765     std::string insert("INSERT INTO ");
766     insert += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
767     insert += " " + val + ";";
768
769     UPDATEDB(insert);
770         
771     // Store DB id of newly created node;
772     long lastrow = mDB->lastRowId();
773     std::stringstream ri;
774     ri << mDB->lastRowId();
775     n->SetAttribute("ID",ri.str());
776   }
777   //======================================================================
778
779   //======================================================================
780   /// Graft the branch defined by the attributes to the parent
781   void SQLiteTreeHandler::DBGraftToParent( tree::Node* parent, 
782                                             const AttributeMapType& attr)
783   {
784     //    std::cout <<"Grafting to parent '"<<parent->GetLabel()
785     //             <<"'"<<std::endl;
786
787     for (int level = parent->GetLevel()+1;
788          level < GetTree().GetNumberOfLevels();
789          level++)
790       {
791         // Create Node
792         tree::Node* child = new tree::Node(parent,attr);
793         child->SetChildrenLoaded(true);
794         if (level>1)
795           {
796             int nc = GetNumberOfChildren(parent)+1;
797             
798             //  std::cout<<"Number of children "<<parent->GetNumberOfChildren()<<std::endl;
799             std::stringstream out;
800             out << nc;
801             SetAttribute(parent,"NumberOfChildren",out.str());
802           }
803
804         // Set PARENT_ID if necessary 
805         if ( parent->GetLevel()>0 )
806           child->SetAttribute("PARENT_ID",parent->GetAttribute("ID"));
807         
808         // Insert in DB
809         DBInsert(child);
810         /*
811         std::string val;
812         SQLAppendAttributesValues(child,val);
813         std::string insert("INSERT INTO ");
814         insert += GetTree().GetLevelDescriptor(child->GetLevel()).GetName();
815         insert += " " + val + ";";
816         UPDATEDB(insert);
817         
818         // Store DB id of newly created node;
819         long lastrow = mDB->lastRowId();
820         std::stringstream ri;
821         ri << mDB->lastRowId();
822         child->SetAttribute("ID",ri.str());
823         */
824         // Down one level
825         parent = child;
826         
827         /*
828         // Insert in TypeId map
829         TypeId ti;
830         ti.type = node->GetType();
831         ti.id = node_id;
832         mTypeIdToNodeMap[ti] = node;
833         //    std::cout << "== Insert TypeId ("<<ti.type<<","<<ti.id<<")"<<std::endl; 
834         // 
835         msw[2].Pause();
836         
837         if (node->GetType()==Node::Patient) summary.added_patients++;
838         if (node->GetType()==Node::Study) summary.added_studies++;
839         if (node->GetType()==Node::Series) summary.added_series++;
840         if (node->GetType()==Node::Image) summary.added_images++;
841         */
842       }
843   }
844   //======================================================================
845
846
847   //===================================================================== 
848   /// Sets an attribute of a Node
849   bool SQLiteTreeHandler::DBSetAttribute(tree::Node* n, 
850                                          const std::string& key,
851                                          const std::string& value)
852   {
853     GimmickMessage(3,"Setting Attribute of '"<<n->GetLabel()<<
854                    "' "<<key<<"='"<<value<<"'"<<std::endl);
855
856     n->SetAttribute(key,value);
857     std::string sql = "UPDATE ";
858     sql += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
859     sql += " SET ";
860     sql += key;
861     sql += " = '";
862     sql += value;
863     sql += "' WHERE ID = '";
864     sql += n->GetAttribute("ID");
865         sql +="'";
866     //    sql += " LIMIT 1";
867     UPDATEDB(sql);
868         return true;
869   }
870
871   //===================================================================== 
872   /// Sets an attribute of a Node
873   void SQLiteTreeHandler::DBSetAttribute(const std::string& levelDescriptor, 
874                               const std::string& key,
875                               const std::string& value,
876                                   const std::string& searchParam, 
877                                   const std::string& searchVal)
878   {
879
880     std::string sql = "UPDATE ";
881     sql += levelDescriptor;
882     sql += " SET ";
883     sql += key;
884     sql += " = '";
885     sql += value;
886     sql += "' WHERE ";
887         sql += searchParam;
888         sql += " = '";
889     sql += searchVal;
890         sql += "'";
891         std::cout<<sql<<std::endl;
892     UPDATEDB(sql);
893   }
894    //=====================================================================
895   void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node)
896   {
897        
898     std::string query = "DELETE FROM ";
899    
900     query += GetTree().GetLevelDescriptor(node->GetLevel()).GetName();
901     query += " WHERE ID='"+ node->GetAttribute("ID") + "';";
902  
903     UPDATEDB(query);
904         GimmickDebugMessage(2,
905                             " Deleting '"
906                                 <<node->GetLabel()<<"' with ID '"
907                             <<node->GetAttribute("ID")
908                             <<"' in level "<< GetTree().GetLevelDescriptor(node->GetLevel()).GetName()
909                             <<std::endl);
910
911
912         if(node->GetNumberOfChildren()!=0)
913         {
914                 Node::ChildrenListType::iterator i;
915                 for (i  = node->GetChildrenList().begin();
916                 i != node->GetChildrenList().end();
917                 i++)
918                 {
919                 DBRecursiveRemoveNode((*i));
920                 }
921         }
922         else if(node->GetLevel()<GetTree().GetNumberOfLevels()-1)
923         {
924                 DBRecursiveRemoveNode(node->GetLevel()+1,node->GetAttribute("ID"));
925     }
926   }
927
928   //=====================================================================
929   void SQLiteTreeHandler::DBRecursiveRemoveNode(int level, std::string parentId)
930   {
931     std::stringstream out;
932         std::stringstream result;
933         out<<"SELECT ID FROM "<<GetTree().GetLevelDescriptor(level).GetName()<<" WHERE PARENT_ID='"<<parentId<<"'";
934                 
935         CppSQLite3Query q;
936         QUERYDB(out.str(),q);
937         
938         while (!q.eof())
939           {
940             for (int fld = 0; fld < q.numFields(); fld++)
941               {
942                           result<<q.getStringField(fld)<<"#";
943               }
944             q.nextRow();
945           }
946           std::string res=result.str();
947           size_t ini=0;
948           size_t fin=0;
949           while(fin<res.size()-1)
950           {
951            fin=res.find('#',ini);
952            DBDelete(GetTree().GetLevelDescriptor(level).GetName(),"ID",res.substr(ini,fin-ini));
953           if(level<GetTree().GetNumberOfLevels()-1)
954           {
955                 DBRecursiveRemoveNode(level+1,res.substr(ini,fin-ini));
956           } 
957            ini=fin+1;
958           }
959           
960     
961   }
962
963   //=====================================================================
964   void SQLiteTreeHandler::DBDelete(std::string levelDescriptor, std::string key, std::string value)
965   {
966        
967     std::stringstream query;
968         query<<"DELETE FROM "<<levelDescriptor<<" WHERE "<<key<<"='"<<value<<"';";
969  
970     UPDATEDB(query.str());
971         GimmickDebugMessage(2," Deleting: Query: "<<query.str()<<std::endl);
972   }
973
974
975   //===================================================================== 
976   void SQLiteTreeHandler::GetAttribute(std::string levelDescriptor,
977                                                                            std::string searchParam, 
978                                                                            std::string searchVal, 
979                                                                            std::string key, 
980                                                                            std::string& result) 
981   { 
982         std::stringstream out;
983         std::stringstream results;
984         out<<"SELECT "<<key<<" FROM "<<levelDescriptor;
985         if(searchParam!="")
986         {
987                 out<<" WHERE "<<searchParam<<"='"<<searchVal<<"'";
988         }
989         
990         CppSQLite3Query q;
991         QUERYDB(out.str(),q);
992         
993         
994         while (!q.eof())
995           {
996             for (int fld = 0; fld < q.numFields(); fld++)
997               {
998                           results<<q.getStringField(fld);
999                           if(searchParam=="")
1000                           {
1001                                   results<<"#";
1002                           }
1003               }
1004             q.nextRow();
1005           }
1006         result=results.str();
1007       
1008   }
1009   //===================================================================== 
1010   unsigned int SQLiteTreeHandler::GetNumberOfChildren(tree::Node* n) 
1011   { 
1012     // Query DB
1013     int nb=0;
1014     int level = n->GetLevel();
1015
1016     if(level<GetTree().GetNumberOfLevels()&& level>0)
1017       {
1018         std::string query = "SELECT NumberOfChildren FROM ";
1019         query += GetTree().GetLevelDescriptor(level).GetName();
1020         if (level>0)
1021           {
1022             query += " WHERE ID='" + n->UnsafeGetAttribute("ID") 
1023               + "'";
1024           }
1025         CppSQLite3Query q;
1026         QUERYDB(query,q);
1027         
1028         
1029         while (!q.eof())
1030           {
1031             for (int fld = 0; fld < q.numFields(); fld++)
1032               {
1033                 nb=q.getIntField(fld);  
1034               }
1035             q.nextRow();
1036           }
1037       }
1038     /*
1039     if(nb==0)
1040       { 
1041         nb=1;
1042       }
1043     */
1044     return nb; 
1045   }
1046
1047   //===================================================================== 
1048   void SQLiteTreeHandler::GetTopLevelNodeId(const std::string& searchParam, const std::string& searchValue, std::string& parent_id) 
1049   {
1050           int level=GetTree().GetNumberOfLevels()-1;
1051           std::string sp=searchParam.c_str();
1052           std::string sv=searchValue.c_str();
1053
1054           while(level>1)
1055           {
1056                 std::stringstream out;
1057                 std::stringstream results;
1058                 out<<"SELECT PARENT_ID FROM "<<GetTree().GetLevelDescriptor(level).GetName();
1059                 out<<" WHERE "<<sp<<"='"<<sv<<"'";      
1060                 CppSQLite3Query q;
1061                 QUERYDB(out.str(),q);
1062                 
1063                 
1064                 while (!q.eof())
1065                 {
1066                         for (int fld = 0; fld < q.numFields(); fld++)
1067                         {
1068                                 results<<q.getStringField(fld);
1069                         }
1070                         q.nextRow();
1071                 }
1072                 level=level-1;
1073                 sp="ID";
1074                 sv=results.str();
1075           }
1076           parent_id=sv;
1077
1078   }
1079
1080   //=====================================================================
1081   void SQLiteTreeHandler::RemoveEntries(const std::string i_table, 
1082                 const std::string i_attribute, 
1083                 const std::string i_operand, 
1084                 const std::string i_val)
1085     {
1086         std::stringstream query;
1087                 query<<"DELETE  FROM "<<i_table<<" WHERE "<<i_attribute<<" "<<i_operand<<" '"<<i_val<<"'";
1088         UPDATEDB(query.str());
1089         }
1090
1091         //=====================================================================
1092   void SQLiteTreeHandler::BeginTransaction()
1093     {
1094                 std::stringstream out;
1095                 out<<"begin transaction;";
1096         UPDATEDB(out.str());
1097         }
1098
1099         //=====================================================================
1100   void SQLiteTreeHandler::EndTransaction()
1101     {
1102        std::stringstream out;
1103                 out<<"commit transaction;";
1104         UPDATEDB(out.str());
1105         }
1106
1107   /*
1108   //=====================================================================
1109   bool SQLiteTreeHandler::DBInsert(Node* alien_node,
1110                                    UpdateSummary& summary)
1111   {
1112     //    std::cout << "SQLiteTreeHandler::Insert('"<<alien_node->GetLabel()
1113     //        <<"')"<<std::endl;
1114     
1115     //    if (!ChildrenLoaded()) DBLoadChildren(this,Node::Database);
1116     
1117     // Find parent
1118     Node* parent;
1119     std::string parent_id; 
1120     parent = DBGetOrCreateParent(alien_node,parent_id,summary);
1121     
1122     // Insert 
1123     DBRecursiveGetOrCreateNode(alien_node,parent,parent_id,summary);
1124    return true;
1125   }
1126   //=====================================================================
1127
1128
1129   //=====================================================================
1130   Node* SQLiteTreeHandler::DBGetOrCreateParent(Node* alien_node,
1131                                                 std::string& parent_id,
1132                                                 UpdateSummary& summary)
1133   {
1134     //    std::cout << "DBGetOrCreateParent '" << alien_node->GetLabel()<<"'"
1135     //        << std::endl;
1136     // Load the patients if not already done
1137     DBLoadChildren(this,Node::Patient);
1138
1139     parent_id = "";
1140     Node* parent = this;
1141
1142     // The chain of ancestors
1143     std::deque<Node*> chain;
1144     Node* cur = alien_node->GetParent();
1145     for (int type=Node::Patient; 
1146          type<alien_node->GetType();++type)
1147       {
1148         chain.push_front(cur);
1149         cur = cur->GetParent();
1150       }
1151
1152     // create the nodes if do not exist
1153     std::deque<Node*>::iterator i;
1154     for (i=chain.begin();i!=chain.end();++i)
1155       {
1156         //      std::cout << " cur = '"<<(*i)->GetLabel()<<"'"<<std::endl;
1157         //      std::string cur_id = DBGetNodeId(*i,parent_id);
1158         //      if (cur_id.size()==0)
1159         //        {
1160         // Node does not exist : create it
1161         std::string cur_id;
1162         parent = DBGetOrCreateNode(*i, 
1163                                         parent,
1164                                         parent_id,
1165                                         cur_id,
1166                                         summary
1167                                         );
1168         DBLoadChildren(parent,parent->GetType()+1);
1169
1170         parent_id = cur_id;
1171       }
1172     return parent;
1173   }
1174   //=====================================================================
1175
1176
1177
1178   //=====================================================================
1179   void SQLiteTreeHandler::DBRecursiveGetOrCreateNode(Node* alien_node, 
1180                                                       Node* parent, 
1181                                                       const std::string& parent_id,
1182                                                       UpdateSummary& summary)
1183   {
1184     //    std::cout << "SQLiteTreeHandler::RecursiveGetOrCreateNode('"
1185     //        <<alien_node->GetLabel()
1186     //        <<"','"<<parent<<"','"<<parent_id<<"')"<<std::endl;
1187     if (parent != 0) 
1188       {
1189         //      std::cout << " -- Parent = '"<<parent->GetLabel()<<"'"<<std::endl;
1190       }   
1191     std::string new_id;
1192     Node* new_node = DBGetOrCreateNode(alien_node, 
1193                                                  parent,
1194                                                  parent_id,
1195                                                  new_id,
1196                                                  summary);
1197     Node::ChildrenListType::iterator i;
1198     for (i  = alien_node->GetChildrenList().begin();
1199          i != alien_node->GetChildrenList().end();
1200          i++)
1201       {
1202         DBRecursiveGetOrCreateNode((*i),new_node,new_id,summary);
1203       }
1204   }
1205   //=====================================================================
1206
1207
1208   //=====================================================================
1209   Node* SQLiteTreeHandler::DBGetOrCreateNode(Node* alien_node, 
1210                                                    Node* internal_parent,
1211                                                    std::string parent_id,
1212                                                    std::string& node_id,
1213                                                    UpdateSummary& summary)
1214   {
1215     //   std::cout << "DBGetOrCreateNode('"<<alien_node->GetLabel()<<"','"
1216     //        << internal_parent << "','"<< parent_id<<"')"<<std::endl;
1217     if (internal_parent != 0) 
1218       {
1219         //      std::cout << " -- Parent = '"<<internal_parent->GetLabel()<<"'"<<std::endl;
1220       }
1221     // Node Exists ? return it 
1222     // First try among children of internal parent 
1223     Node* node = GetChildrenLike(internal_parent,alien_node);
1224     if (node>0)
1225       {
1226         node_id = node->UnsafeGetFieldValue("ID");
1227         return node;
1228       }
1229     // Second : try in DB 
1230    
1231     // Does not exist : Create new one
1232     node = new Node(alien_node->GetType(),this,internal_parent);
1233     node->SetChildrenLoaded(true);
1234     // Copy fields values from alien
1235     Node::FieldValueMapType::iterator i,j;
1236     for (i =  node->GetFieldValueMap().begin();
1237          i != node->GetFieldValueMap().end();
1238          i++)
1239       {
1240         j = alien_node->GetFieldValueMap().find(i->first);
1241         if (j != alien_node->GetFieldValueMap().end() )
1242           {
1243             i->second = j->second;
1244           }
1245       }
1246
1247     msw[2].Resume();
1248     if (node->GetType()!=Node::Patient) 
1249       node->SetFieldValue("PARENT_ID",parent_id);
1250
1251     // Insert in DB
1252     std::string val;
1253     BuildSQLFieldsValues(node,val);
1254     std::string insert("INSERT INTO ");
1255     insert += std::string(SQLiteTreeHandlerStructure::Table(node->GetType())) 
1256       + " " + val + ";";
1257     //    std::cout << "** SQL = '"<<insert<<"'"<<std::endl;
1258     UPDATEDB(insert);
1259     //    std::cout << "** SQL OK"<<std::endl;
1260
1261     // Store DB id of newly created node;
1262     long lastrow = mDB->lastRowId();
1263     std::stringstream ri;
1264     ri << mDB->lastRowId();
1265     node_id = ri.str();
1266     //    std::cout << "LastRowId='"<<mDB->lastRowId()<<"' vs '"<<created_id<<"'"<<std::endl;
1267
1268     node->SetFieldValue("ID",node_id);
1269     // Insert in TypeId map
1270     TypeId ti;
1271     ti.type = node->GetType();
1272     ti.id = node_id;
1273     mTypeIdToNodeMap[ti] = node;
1274     //    std::cout << "== Insert TypeId ("<<ti.type<<","<<ti.id<<")"<<std::endl; 
1275     // 
1276     msw[2].Pause();
1277
1278     if (node->GetType()==Node::Patient) summary.added_patients++;
1279     if (node->GetType()==Node::Study) summary.added_studies++;
1280     if (node->GetType()==Node::Series) summary.added_series++;
1281     if (node->GetType()==Node::Image) summary.added_images++;
1282
1283     return node;
1284   }
1285   //=====================================================================
1286
1287   //=====================================================================
1288   Node* SQLiteTreeHandler::GetChildrenLike(Node* parent,
1289                                             Node* alien_node)
1290   {
1291     Node::ChildrenListType::iterator i;
1292     for (i  = parent->GetChildrenList().begin();
1293          i != parent->GetChildrenList().end();
1294          i++)
1295       {
1296         Node::Type type = alien_node->GetType();
1297         bool ok = true;
1298         for (int j=0;
1299              j<SQLiteTreeHandlerStructure::NbQueryFields(type);
1300              j++) 
1301           {
1302             if ( 
1303                 alien_node->GetFieldValue(SQLiteTreeHandlerStructure::
1304                                     QueryField(type,j).key )   !=
1305                 (*i)->GetFieldValue(SQLiteTreeHandlerStructure::
1306                                     QueryField(type,j).key ) )
1307               {
1308                 ok = false;
1309                 break;
1310               }
1311           }
1312         if (ok) 
1313           {
1314             return (*i);
1315           }
1316       }
1317     return 0;    
1318   }
1319   //=====================================================================
1320
1321   //=====================================================================
1322   std::string SQLiteTreeHandler::DBGetNodeId(Node* node, 
1323                                               const std::string& parent_id)
1324   {
1325     //    std::cout << "SQLiteTreeHandler::DBGetNodeId('"<<node->GetLabel()
1326     //        <<"','"<<parent_id<<"')"
1327     //        <<std::endl;
1328     msw[2].Resume();
1329     int type = node->GetType();
1330
1331     std::string table = SQLiteTreeHandlerStructure::Table(type);
1332     std::string where = "WHERE ";
1333     
1334     if (type!=Node::Patient)
1335       {
1336         where += "PARENT_ID='" + parent_id 
1337           //node->GetFieldValue("PARENT_ID") 
1338           + "' AND ";
1339       }
1340
1341     for (int i=0;i<SQLiteTreeHandlerStructure::NbQueryFields(type);i++) 
1342       {
1343         where += SQLiteTreeHandlerStructure::QueryField(type,i).key + "='"
1344           + node->GetFieldValue(SQLiteTreeHandlerStructure::QueryField(type,i).key) + "' ";
1345         if (i<SQLiteTreeHandlerStructure::NbQueryFields(type)-1)
1346           where += "AND ";
1347     }
1348
1349     std::string query = "SELECT ID FROM " + table + " " + where + ";";                                                    
1350     //    std::cout << "** SQL = '"<<query<<"'"<<std::endl;
1351     CppSQLite3Query q;
1352     QUERYDB(query,q);
1353
1354     if (!q.eof())
1355       {
1356         
1357         //      std::cout << " - Node exists " << std::endl;
1358         std::string id = q.getStringField(0);
1359         //      std::cout << " id = '"<<id<<"'"<<std::endl;
1360         msw[2].Pause();
1361         return id;
1362       }
1363     msw[2].Pause();
1364     return "";
1365   }
1366   //=====================================================================
1367
1368
1369
1370   //=====================================================================
1371   Node* SQLiteTreeHandler::GetNodeFromTypeId(Node::Type type,
1372                                        const std::string& id)
1373   {
1374     //    std::cout << "GetNodeFromTypeId("<<type<<","<<id<<")"<<std::endl;
1375
1376     TypeId ti;
1377     ti.type = type;
1378     ti.id = id;
1379     
1380     TypeIdToNodeMapType::iterator i = mTypeIdToNodeMap.find(ti);
1381     if (i == mTypeIdToNodeMap.end())
1382       {
1383
1384             std::cout << "Internal error : mTypeIdToNodeMap does not contain key"
1385                       << std::endl;
1386             creaError("Internal error : mTypeIdToNodeMap does not contain key");
1387             // }
1388       }
1389
1390     //    std::cout << " ** Node = "<<i->second<<std::endl;
1391     return i->second;
1392   }
1393  
1394   //=====================================================================
1395
1396   //=====================================================================
1397   bool SQLiteTreeHandler::Remove(Node* node)
1398   {
1399
1400     //DBRecursiveRemoveNode(node);
1401  
1402     //    std::cout << "DELETE"<<std::endl;
1403     if (node->GetParent())
1404       {
1405         node->GetParent()->RemoveChildrenFromList(node);
1406       }
1407     delete node;
1408     //    std::cout << "DELETE OK"<<std::endl;
1409     return true;
1410   }
1411   
1412   
1413   //========================================================================
1414
1415   //=====================================================================
1416   void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node)
1417   {
1418     //    std::cout << "SQLiteTreeHandler::DBRecursiveRemoveNode('"
1419     //        <<node->GetLabel()<<"')"<<std::endl;
1420
1421     std::string query = "DELETE FROM ";
1422     query += SQLiteTreeHandlerStructure::Table(node->GetType());
1423     query += " WHERE ID='"+ node->GetFieldValue("ID") + "';";
1424  
1425     UPDATEDB(query);
1426
1427     Node::ChildrenListType::iterator i;
1428     for (i  = node->GetChildrenList().begin();
1429          i != node->GetChildrenList().end();
1430          i++)
1431       {
1432         DBRecursiveRemoveNode((*i));
1433       }
1434   }
1435   
1436   //=====================================================================
1437   
1438   //=====================================================================
1439   int SQLiteTreeHandler::DBQueryNumberOfChildren(Node* node)
1440   {
1441     std::string query = "SELECT COUNT (ID) FROM ";
1442     query += SQLiteTreeHandlerStructure::Table(node->GetType()+1);
1443     if (node->GetType() != Node::Database) 
1444       {
1445         query += " WHERE PARENT_ID='"+ node->GetFieldValue("ID")+"'";
1446       }
1447     query  += ";";
1448     
1449     //   std::cout << "**SQL = "<< query << std::endl;
1450     
1451     CppSQLite3Query q;
1452     QUERYDB(query,q);
1453    
1454      //    std::cout << "**RES = "<< q.getIntField(0) <<std::endl;
1455
1456     return q.getIntField(0);
1457   }
1458   //=====================================================================
1459  
1460  
1461
1462 */
1463
1464
1465
1466 } // namespace creaImageIO