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