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