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