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