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