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