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