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