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