]> Creatis software - creaImageIO.git/blob - src2/creaImageIOSQLiteTreeHandler.cpp
Fixed a bug that didn't let it load on opening. Still exists a bug on adding.
[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
675         return nbloaded;
676
677       }
678         else
679         {
680     /// If children not loaded : do it and recurse
681  std::cout<<"Children are not loaded for node:"<<node->GetLabel()<<std::endl;
682  std::cout<<"Children are not loaded for node (pointer):"<<node<<std::endl;
683
684     // Query DB
685     int level = node->GetLevel();
686     std::string query = "SELECT * FROM ";
687         
688     query += GetTree().GetLevelDescriptor(level+1).GetName();
689     if (level>0)
690       {
691         query += " WHERE PARENT_ID='" + node->UnsafeGetAttribute("ID") 
692           + "'";
693       }
694     CppSQLite3Query q;
695     QUERYDB(query,q);
696
697         int p=0;
698     while (!q.eof())
699       {
700         nbloaded++;
701         Node* n = new Node(node);
702         for (int fld = 0; fld < q.numFields(); fld++)
703           {
704             n->UnsafeSetAttribute(q.fieldName(fld),q.getStringField(fld));          
705           }
706         /*
707         // Index 
708         TypeId ti;
709         ti.type = type;
710         ti.id = n->GetFieldValue("ID");    
711         mTypeIdToNodeMap[ti] = n;
712         */
713         // recurse 
714         if ( numberoflevels != 1 ) 
715           {
716             //  msw[2].Pause();
717             nbloaded += DBLoadChildren(n, numberoflevels-1);
718             //      msw[2].Resume();
719           }
720         // next entry in db
721         q.nextRow();
722       }
723
724     node->SetChildrenLoaded(true);
725         
726     
727     //    msw[2].Pause();
728     return nbloaded;
729         }
730   }
731   //=====================================================================
732
733   //======================================================================
734   void SQLiteTreeHandler::DBInsert(tree::Node* n)
735   {
736     GimmickMessage(2,"Inserting in DB '"<<n->GetLabel()
737                    <<"'"<<std::endl);
738     std::string val;
739     SQLAppendAttributesValues(n,val);
740     std::string insert("INSERT INTO ");
741     insert += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
742     insert += " " + val + ";";
743
744     UPDATEDB(insert);
745         
746     // Store DB id of newly created node;
747     long lastrow = mDB->lastRowId();
748     std::stringstream ri;
749     ri << mDB->lastRowId();
750     n->SetAttribute("ID",ri.str());
751   }
752   //======================================================================
753
754   //======================================================================
755   /// Graft the branch defined by the attributes to the parent
756   void SQLiteTreeHandler::DBGraftToParent( tree::Node* parent, 
757                                             const AttributeMapType& attr)
758   {
759     GimmickMessage(2,"Grafting to parent '"<<parent->GetLabel()
760                    <<"'"<<std::endl);
761
762     for (int level = parent->GetLevel()+1;
763          level < GetTree().GetNumberOfLevels();
764          level++)
765       {
766         // Create Node
767         tree::Node* child = new tree::Node(parent,attr);
768         std::cout<<"Number of children "<<parent->GetNumberOfChildren()<<std::endl;
769         // Set PARENT_ID if necessary 
770         if ( parent->GetLevel()>0 )
771           child->SetAttribute("PARENT_ID",parent->GetAttribute("ID"));
772         
773         // Insert in DB
774         DBInsert(child);
775         /*
776         std::string val;
777         SQLAppendAttributesValues(child,val);
778         std::string insert("INSERT INTO ");
779         insert += GetTree().GetLevelDescriptor(child->GetLevel()).GetName();
780         insert += " " + val + ";";
781         UPDATEDB(insert);
782         
783         // Store DB id of newly created node;
784         long lastrow = mDB->lastRowId();
785         std::stringstream ri;
786         ri << mDB->lastRowId();
787         child->SetAttribute("ID",ri.str());
788         */
789         // Down one level
790         parent = child;
791         
792         /*
793         // Insert in TypeId map
794         TypeId ti;
795         ti.type = node->GetType();
796         ti.id = node_id;
797         mTypeIdToNodeMap[ti] = node;
798         //    std::cout << "== Insert TypeId ("<<ti.type<<","<<ti.id<<")"<<std::endl; 
799         // 
800         msw[2].Pause();
801         
802         if (node->GetType()==Node::Patient) summary.added_patients++;
803         if (node->GetType()==Node::Study) summary.added_studies++;
804         if (node->GetType()==Node::Series) summary.added_series++;
805         if (node->GetType()==Node::Image) summary.added_images++;
806         */
807       }
808   }
809   //======================================================================
810
811
812   //===================================================================== 
813   /// Sets an attribute of a Node
814   bool SQLiteTreeHandler::DBSetAttribute(tree::Node* n, 
815                                          const std::string& key,
816                                          const std::string& value)
817   {
818     GimmickMessage(3,"Setting Attribute of '"<<n->GetLabel()<<
819                    "' "<<key<<"='"<<value<<"'"<<std::endl);
820
821     n->SetAttribute(key,value);
822     std::string sql = "UPDATE ";
823     sql += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
824     sql += " SET ";
825     sql += key;
826     sql += "='";
827     sql += value;
828     sql += "' WHERE ID=";
829     sql += n->GetAttribute("ID");
830     //    sql += " LIMIT 1";
831     UPDATEDB(sql);
832   }
833   //===================================================================== 
834
835
836   //=====================================================================
837   void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node)
838   {
839        
840     std::string query = "DELETE FROM ";
841    
842     query += GetTree().GetLevelDescriptor(node->GetLevel()).GetName();
843     query += " WHERE ID='"+ node->GetAttribute("ID") + "';";
844  
845     UPDATEDB(query);
846         GimmickDebugMessage(2,
847                             " Deleting '"
848                                 <<node->GetLabel()<<"' with ID '"
849                             <<node->GetAttribute("ID")
850                             <<"' in level "<< GetTree().GetLevelDescriptor(node->GetLevel()).GetName()
851                             <<std::endl);
852
853     Node::ChildrenListType::iterator i;
854     for (i  = node->GetChildrenList().begin();
855          i != node->GetChildrenList().end();
856          i++)
857       {
858         DBRecursiveRemoveNode((*i));
859       }
860   }
861
862   //===================================================================== 
863   unsigned int SQLiteTreeHandler::GetNumberOfChildren(tree::Node* n) 
864   { 
865           // Query DB
866         int nb=0;
867     int level = n->GetLevel();
868         if(GetTree().GetNumberOfLevels()!=(level+1))
869         {
870         std::string query = "SELECT * FROM ";
871     query += GetTree().GetLevelDescriptor(level+1).GetName();
872     if (level>0)
873       {
874         query += " WHERE PARENT_ID='" + n->UnsafeGetAttribute("ID") 
875           + "'";
876       }
877
878     CppSQLite3Query q;
879     QUERYDB(query,q);
880         
881
882                 while (!q.eof())
883                 {
884                         nb++;
885                         q.nextRow();
886                 }
887         }
888     return nb; 
889   }
890
891   /*
892   //=====================================================================
893   bool SQLiteTreeHandler::DBInsert(Node* alien_node,
894                                    UpdateSummary& summary)
895   {
896     //    std::cout << "SQLiteTreeHandler::Insert('"<<alien_node->GetLabel()
897     //        <<"')"<<std::endl;
898     
899     //    if (!ChildrenLoaded()) DBLoadChildren(this,Node::Database);
900     
901     // Find parent
902     Node* parent;
903     std::string parent_id; 
904     parent = DBGetOrCreateParent(alien_node,parent_id,summary);
905     
906     // Insert 
907     DBRecursiveGetOrCreateNode(alien_node,parent,parent_id,summary);
908    return true;
909   }
910   //=====================================================================
911
912
913   //=====================================================================
914   Node* SQLiteTreeHandler::DBGetOrCreateParent(Node* alien_node,
915                                                 std::string& parent_id,
916                                                 UpdateSummary& summary)
917   {
918     //    std::cout << "DBGetOrCreateParent '" << alien_node->GetLabel()<<"'"
919     //        << std::endl;
920     // Load the patients if not already done
921     DBLoadChildren(this,Node::Patient);
922
923     parent_id = "";
924     Node* parent = this;
925
926     // The chain of ancestors
927     std::deque<Node*> chain;
928     Node* cur = alien_node->GetParent();
929     for (int type=Node::Patient; 
930          type<alien_node->GetType();++type)
931       {
932         chain.push_front(cur);
933         cur = cur->GetParent();
934       }
935
936     // create the nodes if do not exist
937     std::deque<Node*>::iterator i;
938     for (i=chain.begin();i!=chain.end();++i)
939       {
940         //      std::cout << " cur = '"<<(*i)->GetLabel()<<"'"<<std::endl;
941         //      std::string cur_id = DBGetNodeId(*i,parent_id);
942         //      if (cur_id.size()==0)
943         //        {
944         // Node does not exist : create it
945         std::string cur_id;
946         parent = DBGetOrCreateNode(*i, 
947                                         parent,
948                                         parent_id,
949                                         cur_id,
950                                         summary
951                                         );
952         DBLoadChildren(parent,parent->GetType()+1);
953
954         parent_id = cur_id;
955       }
956     return parent;
957   }
958   //=====================================================================
959
960
961
962   //=====================================================================
963   void SQLiteTreeHandler::DBRecursiveGetOrCreateNode(Node* alien_node, 
964                                                       Node* parent, 
965                                                       const std::string& parent_id,
966                                                       UpdateSummary& summary)
967   {
968     //    std::cout << "SQLiteTreeHandler::RecursiveGetOrCreateNode('"
969     //        <<alien_node->GetLabel()
970     //        <<"','"<<parent<<"','"<<parent_id<<"')"<<std::endl;
971     if (parent != 0) 
972       {
973         //      std::cout << " -- Parent = '"<<parent->GetLabel()<<"'"<<std::endl;
974       }   
975     std::string new_id;
976     Node* new_node = DBGetOrCreateNode(alien_node, 
977                                                  parent,
978                                                  parent_id,
979                                                  new_id,
980                                                  summary);
981     Node::ChildrenListType::iterator i;
982     for (i  = alien_node->GetChildrenList().begin();
983          i != alien_node->GetChildrenList().end();
984          i++)
985       {
986         DBRecursiveGetOrCreateNode((*i),new_node,new_id,summary);
987       }
988   }
989   //=====================================================================
990
991
992   //=====================================================================
993   Node* SQLiteTreeHandler::DBGetOrCreateNode(Node* alien_node, 
994                                                    Node* internal_parent,
995                                                    std::string parent_id,
996                                                    std::string& node_id,
997                                                    UpdateSummary& summary)
998   {
999     //   std::cout << "DBGetOrCreateNode('"<<alien_node->GetLabel()<<"','"
1000     //        << internal_parent << "','"<< parent_id<<"')"<<std::endl;
1001     if (internal_parent != 0) 
1002       {
1003         //      std::cout << " -- Parent = '"<<internal_parent->GetLabel()<<"'"<<std::endl;
1004       }
1005     // Node Exists ? return it 
1006     // First try among children of internal parent 
1007     Node* node = GetChildrenLike(internal_parent,alien_node);
1008     if (node>0)
1009       {
1010         node_id = node->UnsafeGetFieldValue("ID");
1011         return node;
1012       }
1013     // Second : try in DB 
1014    
1015     // Does not exist : Create new one
1016     node = new Node(alien_node->GetType(),this,internal_parent);
1017     node->SetChildrenLoaded(true);
1018     // Copy fields values from alien
1019     Node::FieldValueMapType::iterator i,j;
1020     for (i =  node->GetFieldValueMap().begin();
1021          i != node->GetFieldValueMap().end();
1022          i++)
1023       {
1024         j = alien_node->GetFieldValueMap().find(i->first);
1025         if (j != alien_node->GetFieldValueMap().end() )
1026           {
1027             i->second = j->second;
1028           }
1029       }
1030
1031     msw[2].Resume();
1032     if (node->GetType()!=Node::Patient) 
1033       node->SetFieldValue("PARENT_ID",parent_id);
1034
1035     // Insert in DB
1036     std::string val;
1037     BuildSQLFieldsValues(node,val);
1038     std::string insert("INSERT INTO ");
1039     insert += std::string(SQLiteTreeHandlerStructure::Table(node->GetType())) 
1040       + " " + val + ";";
1041     //    std::cout << "** SQL = '"<<insert<<"'"<<std::endl;
1042     UPDATEDB(insert);
1043     //    std::cout << "** SQL OK"<<std::endl;
1044
1045     // Store DB id of newly created node;
1046     long lastrow = mDB->lastRowId();
1047     std::stringstream ri;
1048     ri << mDB->lastRowId();
1049     node_id = ri.str();
1050     //    std::cout << "LastRowId='"<<mDB->lastRowId()<<"' vs '"<<created_id<<"'"<<std::endl;
1051
1052     node->SetFieldValue("ID",node_id);
1053     // Insert in TypeId map
1054     TypeId ti;
1055     ti.type = node->GetType();
1056     ti.id = node_id;
1057     mTypeIdToNodeMap[ti] = node;
1058     //    std::cout << "== Insert TypeId ("<<ti.type<<","<<ti.id<<")"<<std::endl; 
1059     // 
1060     msw[2].Pause();
1061
1062     if (node->GetType()==Node::Patient) summary.added_patients++;
1063     if (node->GetType()==Node::Study) summary.added_studies++;
1064     if (node->GetType()==Node::Series) summary.added_series++;
1065     if (node->GetType()==Node::Image) summary.added_images++;
1066
1067     return node;
1068   }
1069   //=====================================================================
1070
1071   //=====================================================================
1072   Node* SQLiteTreeHandler::GetChildrenLike(Node* parent,
1073                                             Node* alien_node)
1074   {
1075     Node::ChildrenListType::iterator i;
1076     for (i  = parent->GetChildrenList().begin();
1077          i != parent->GetChildrenList().end();
1078          i++)
1079       {
1080         Node::Type type = alien_node->GetType();
1081         bool ok = true;
1082         for (int j=0;
1083              j<SQLiteTreeHandlerStructure::NbQueryFields(type);
1084              j++) 
1085           {
1086             if ( 
1087                 alien_node->GetFieldValue(SQLiteTreeHandlerStructure::
1088                                     QueryField(type,j).key )   !=
1089                 (*i)->GetFieldValue(SQLiteTreeHandlerStructure::
1090                                     QueryField(type,j).key ) )
1091               {
1092                 ok = false;
1093                 break;
1094               }
1095           }
1096         if (ok) 
1097           {
1098             return (*i);
1099           }
1100       }
1101     return 0;    
1102   }
1103   //=====================================================================
1104
1105   //=====================================================================
1106   std::string SQLiteTreeHandler::DBGetNodeId(Node* node, 
1107                                               const std::string& parent_id)
1108   {
1109     //    std::cout << "SQLiteTreeHandler::DBGetNodeId('"<<node->GetLabel()
1110     //        <<"','"<<parent_id<<"')"
1111     //        <<std::endl;
1112     msw[2].Resume();
1113     int type = node->GetType();
1114
1115     std::string table = SQLiteTreeHandlerStructure::Table(type);
1116     std::string where = "WHERE ";
1117     
1118     if (type!=Node::Patient)
1119       {
1120         where += "PARENT_ID='" + parent_id 
1121           //node->GetFieldValue("PARENT_ID") 
1122           + "' AND ";
1123       }
1124
1125     for (int i=0;i<SQLiteTreeHandlerStructure::NbQueryFields(type);i++) 
1126       {
1127         where += SQLiteTreeHandlerStructure::QueryField(type,i).key + "='"
1128           + node->GetFieldValue(SQLiteTreeHandlerStructure::QueryField(type,i).key) + "' ";
1129         if (i<SQLiteTreeHandlerStructure::NbQueryFields(type)-1)
1130           where += "AND ";
1131     }
1132
1133     std::string query = "SELECT ID FROM " + table + " " + where + ";";                                                    
1134     //    std::cout << "** SQL = '"<<query<<"'"<<std::endl;
1135     CppSQLite3Query q;
1136     QUERYDB(query,q);
1137
1138     if (!q.eof())
1139       {
1140         
1141         //      std::cout << " - Node exists " << std::endl;
1142         std::string id = q.getStringField(0);
1143         //      std::cout << " id = '"<<id<<"'"<<std::endl;
1144         msw[2].Pause();
1145         return id;
1146       }
1147     msw[2].Pause();
1148     return "";
1149   }
1150   //=====================================================================
1151
1152
1153
1154   //=====================================================================
1155   Node* SQLiteTreeHandler::GetNodeFromTypeId(Node::Type type,
1156                                        const std::string& id)
1157   {
1158     //    std::cout << "GetNodeFromTypeId("<<type<<","<<id<<")"<<std::endl;
1159
1160     TypeId ti;
1161     ti.type = type;
1162     ti.id = id;
1163     
1164     TypeIdToNodeMapType::iterator i = mTypeIdToNodeMap.find(ti);
1165     if (i == mTypeIdToNodeMap.end())
1166       {
1167
1168             std::cout << "Internal error : mTypeIdToNodeMap does not contain key"
1169                       << std::endl;
1170             creaError("Internal error : mTypeIdToNodeMap does not contain key");
1171             // }
1172       }
1173
1174     //    std::cout << " ** Node = "<<i->second<<std::endl;
1175     return i->second;
1176   }
1177  
1178   //=====================================================================
1179
1180   //=====================================================================
1181   bool SQLiteTreeHandler::Remove(Node* node)
1182   {
1183
1184     //DBRecursiveRemoveNode(node);
1185  
1186     //    std::cout << "DELETE"<<std::endl;
1187     if (node->GetParent())
1188       {
1189         node->GetParent()->RemoveChildrenFromList(node);
1190       }
1191     delete node;
1192     //    std::cout << "DELETE OK"<<std::endl;
1193     return true;
1194   }
1195   
1196   
1197   //========================================================================
1198
1199   //=====================================================================
1200   void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node)
1201   {
1202     //    std::cout << "SQLiteTreeHandler::DBRecursiveRemoveNode('"
1203     //        <<node->GetLabel()<<"')"<<std::endl;
1204
1205     std::string query = "DELETE FROM ";
1206     query += SQLiteTreeHandlerStructure::Table(node->GetType());
1207     query += " WHERE ID='"+ node->GetFieldValue("ID") + "';";
1208  
1209     UPDATEDB(query);
1210
1211     Node::ChildrenListType::iterator i;
1212     for (i  = node->GetChildrenList().begin();
1213          i != node->GetChildrenList().end();
1214          i++)
1215       {
1216         DBRecursiveRemoveNode((*i));
1217       }
1218   }
1219   
1220   //=====================================================================
1221   
1222   //=====================================================================
1223   int SQLiteTreeHandler::DBQueryNumberOfChildren(Node* node)
1224   {
1225     std::string query = "SELECT COUNT (ID) FROM ";
1226     query += SQLiteTreeHandlerStructure::Table(node->GetType()+1);
1227     if (node->GetType() != Node::Database) 
1228       {
1229         query += " WHERE PARENT_ID='"+ node->GetFieldValue("ID")+"'";
1230       }
1231     query  += ";";
1232     
1233     //   std::cout << "**SQL = "<< query << std::endl;
1234     
1235     CppSQLite3Query q;
1236     QUERYDB(query,q);
1237    
1238      //    std::cout << "**RES = "<< q.getIntField(0) <<std::endl;
1239
1240     return q.getIntField(0);
1241   }
1242   //=====================================================================
1243  
1244  
1245
1246 */
1247
1248
1249
1250 } // namespace creaImageIO