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