]> Creatis software - creaImageIO.git/blob - src2/creaImageIOTimestampDatabaseHandler.cpp
167224be19496f29074a278b5c30343f542a8fb2
[creaImageIO.git] / src2 / creaImageIOTimestampDatabaseHandler.cpp
1 #include <creaImageIOTimestampDatabaseHandler.h>
2 #include <creaImageIOSystem.h>
3
4 #include "CppSQLite3.h"
5
6 #include <sys/stat.h>
7
8 #include <deque>
9
10 #include "wx/wx.h"
11 #include <wx/dir.h>
12 #include <wx/filename.h>
13
14 #include <creaWx.h>
15 using namespace crea;
16
17 #include <boost/filesystem.hpp>
18 #include <boost/algorithm/string/replace.hpp>
19
20 namespace creaImageIO
21 {
22         using namespace tree;
23   //=============================================================
24   TimestampDatabaseHandler::TimestampDatabaseHandler(const std::string& filename)
25     : mFileName(filename)
26   {
27     mDB = new CppSQLite3DB;
28     GimmickMessage(1,"SQLite version : "
29                    <<std::string(mDB->SQLiteVersion())<< std::endl);
30   }
31   //=============================================================
32
33   //=============================================================
34   TimestampDatabaseHandler::~TimestampDatabaseHandler()
35   {
36     delete mDB;
37   }
38   //=============================================================
39   //=====================================================================
40   bool TimestampDatabaseHandler::Open()
41   {
42     return DBOpen();
43   }
44
45   //=====================================================================
46   bool TimestampDatabaseHandler::Create()
47   {
48     return DBCreate();
49   }
50   //=====================================================================
51
52
53   //=====================================================================
54   bool TimestampDatabaseHandler::Close()
55   {
56     return true;
57   }
58   //=====================================================================
59
60
61   //=====================================================================
62   bool TimestampDatabaseHandler::Destroy()
63   {
64     return false;
65   }
66
67
68
69
70
71
72   //=====================================================================
73   // SQLite DB specific methods
74   //=====================================================================
75   //=====================================================================
76 #define QUERYTIMESTAMPDB(QUER,RES)                                              \
77     try                                                                 \
78       {                                                                 \
79         GimmickMessage(2,"SQL query: '"<<QUER<<"'"<<std::endl);         \
80         RES = mDB->execQuery(QUER.c_str());                             \
81       }                                                                 \
82     catch (CppSQLite3Exception& e)                                      \
83       {                                                                 \
84         GimmickError("SQLite query '"<<QUER<<"' : "                     \
85                      << e.errorCode() << ":"                            \
86                      << e.errorMessage() );                             \
87       }                                                                 \
88   //=====================================================================
89 #define UPDATETIMESTAMPDB(UP)                                                   \
90   try                                                                   \
91     {                                                                   \
92       GimmickMessage(2,"SQL update: '"<<UP<<"'"<<std::endl);            \
93       mDB->execDML(UP.c_str());                                         \
94     }                                                                   \
95   catch (CppSQLite3Exception& e)                                        \
96     {                                                                   \
97       GimmickError("SQLite update '"<<UP<<"' Error : "                  \
98                    << e.errorCode() << ":"                              \
99                    << e.errorMessage() );                               \
100     }                                                                   
101   //=====================================================================
102
103
104    //=====================================================================
105   bool TimestampDatabaseHandler::DBOpen()
106   {
107     GimmickMessage(1,"Opening SQLite database '"<<GetFileName()
108                    <<"' ... "<<std::endl);
109     // OPENING FILE
110     if (!boost::filesystem::exists(GetFileName())) 
111       {
112         return false;
113       }
114
115     try
116       {
117         mDB->open(GetFileName().c_str());
118       }
119     catch (CppSQLite3Exception& e)
120       {
121         GimmickError("Opening '"<<GetFileName()<<"' : "
122                      << e.errorCode() << ":" 
123                      << e.errorMessage());
124         return false;
125       }
126
127     GimmickDebugMessage(1,"Opening SQLite database '"<<GetFileName()
128                    <<"' ... OK"<<std::endl);
129     return true;
130   }
131   //=====================================================================
132
133   //=====================================================================
134   bool TimestampDatabaseHandler::DBCreate()
135   {
136     GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
137                    <<"' ... "<<std::endl);
138
139     if (boost::filesystem::exists(GetFileName())) 
140       {
141         GimmickError(GetFileName()<<"' : "
142                      << "file already exists");
143         return false;
144       }
145     
146     // OPENING
147     try
148       {
149         mDB->open(GetFileName().c_str());
150       }
151     catch (CppSQLite3Exception& e)
152       {
153         GimmickError(e.errorCode() << ":" 
154                      << e.errorMessage() <<std::endl);
155         return false;
156       }
157     
158      
159     // CREATING TABLES
160     
161     std::string command;
162   
163     
164             command = "CREATE TABLE ";
165             command += "FILES";
166             command += "\n(\nID INTEGER PRIMARY KEY";
167                 command += ",\nPARENT_ID int not null"; 
168             command += ",\nPATH text";
169                 command += ",\nLastModified datetext";
170                 command += ",\nLastRead datetext";
171                 command += ",\nTopLevelNodeId text";
172                 command += ",\nReferencedDB text";
173                 command += ",\nconstraint FK_PARENT foreign key (PARENT_ID) references ";
174                 command += "FILES";
175                 command += "(ID) on delete restrict on update restrict";
176               
177             command += "\n)";
178             UPDATETIMESTAMPDB(command);
179             
180     return true;
181   }
182
183
184
185   //=====================================================================
186   void TimestampDatabaseHandler::CleanPath(std::string& str) const
187   {
188          size_t pos;
189          do
190      {
191          pos = str.find('\\');
192          if ((int)pos!=-1)  
193                  {
194                          str.replace(pos, 1, "/");
195                  }
196      }
197      while ((int)pos!=-1);
198   }
199   //=====================================================================
200
201   bool TimestampDatabaseHandler::AddDirectory(const std::string& parent,
202                                                                                    const std::string& path, 
203                                                                                    const time_t lastModif, 
204                                                                                    const time_t lastRead,
205                                                                                    const std::string& refdb)
206   {
207          bool valid=false;
208          std::string par=parent.c_str();
209          std::string pat=path.c_str();
210          CleanPath(par);
211          CleanPath(pat);
212
213          std::string pathId=IsIndexed(pat,refdb);
214          //Case: It is a root parent
215          if(parent.compare("")==0)
216          {
217                  if(pathId.compare("")==0)
218                  {
219                         AddFile(pat,lastModif,lastRead,refdb);
220                         valid=true;
221                  }
222                  else
223                  {
224                          valid=CheckTimestamp(pathId, lastModif, refdb);
225                  }
226          }
227          else 
228          {
229                  std::string parentId=IsIndexed(par,refdb);
230                  //Case: Parent is not in database
231                  if(parentId.compare("")==0)
232                 {
233                         AddFile(par,lastModif,lastRead,refdb);
234                         parentId=IsIndexed(par,refdb);
235                 }
236
237                 //Case path is not in database
238                 if(pathId.compare("")==0)
239                 {
240                     AddFile(parentId,pat,lastModif,lastRead,refdb);
241                         valid=true;
242                 }
243                 //Parent and path are in the database
244                 else
245                 {
246                         SetAttribute("PARENT_ID",parentId,"ID", pathId);
247                         valid=CheckTimestamp(pathId, lastModif, refdb);
248                 }
249          }
250          return valid;
251         
252   }
253
254   //=====================================================================
255
256   void TimestampDatabaseHandler::AddFile(const std::string& path, const time_t lastModif, const time_t lastRead,  const std::string& refdb)
257   {
258         std::stringstream out;
259         out<<"INSERT INTO FILES (PARENT_ID,PATH,LastModified,LastRead,ReferencedDB) VALUES(0,'"<<path<<"',";
260         out<<lastModif<<","<<lastRead<<",'"<<refdb<<"');";
261     UPDATETIMESTAMPDB(out.str());
262         
263   }
264
265    //=====================================================================
266
267   void TimestampDatabaseHandler::AddFile(const std::string& parentId, 
268                                                                                  const std::string& path, 
269                                                                                  const time_t lastModif, 
270                                                                                  const time_t lastRead,  
271                                                                                  const std::string& refdb)
272   {
273         std::stringstream out;
274         out<<"INSERT INTO FILES (PARENT_ID,PATH,LastModified,LastRead,ReferencedDB) VALUES("<<parentId<<",'"<<path<<"',";
275         out<<lastModif<<","<<lastRead<<",'"<<refdb<<"');";
276     UPDATETIMESTAMPDB(out.str());
277   }
278
279   //=====================================================================
280   std::string TimestampDatabaseHandler::IsIndexed(const std::string& path, const std::string& refdb)
281   {
282         std::stringstream out;
283         std::stringstream result;
284         out<<"SELECT ID FROM FILES WHERE PATH='"<<path<<"' AND REFERENCEDDB='"<<refdb<<"';";
285                 
286         CppSQLite3Query q;
287         QUERYTIMESTAMPDB(out.str(),q);
288         
289         
290         while (!q.eof())
291           {
292             for (int fld = 0; fld < q.numFields(); fld++)
293               {
294                           result<<q.getStringField(fld);
295               }
296             q.nextRow();
297           }
298
299           return result.str();
300   }
301
302   //=====================================================================
303   void TimestampDatabaseHandler::SetAttribute(const std::string& attName, 
304                                                                                         const std::string& attValue,
305                                                                                         const std::string& searchParam,
306                                                                                         const std::string& searchValue)
307   {
308         std::string av=attValue.c_str();
309         std::string sv=searchValue.c_str();
310         CleanPath(av);
311         CleanPath(sv);
312
313         std::string sql = "UPDATE FILES SET ";
314     sql += attName;
315     sql += " = '";
316     sql += av;
317     sql += "' WHERE ";
318         sql += searchParam;
319         sql += " = '";
320     sql += sv;
321         sql += "'";
322     UPDATETIMESTAMPDB(sql);
323   }
324  
325   //=====================================================================
326   void TimestampDatabaseHandler::RemoveNode(const std::string& searchAtt, const tree::Node* node, const std::string& refdb)
327   {
328           int n=node->GetNumberOfChildren();
329           if(n>0)
330           {
331                   std::vector<tree::Node*> children=node->GetChildrenList();
332                   std::vector<tree::Node*>::iterator it;
333                   for(it=children.begin();it!=children.end();++it)
334                   {
335                           RemoveNode(searchAtt,(*it),refdb);
336                   }
337           }
338           else if(node->GetLevel()==3)
339           {
340                   RemoveFile(searchAtt,node->GetAttribute("FullFileName"),refdb);
341           }
342           else
343           {
344                   DBRemove("TopLevelNodeId",node->GetAttribute("ID"),refdb);
345           }
346
347
348   }
349   //=====================================================================
350   void TimestampDatabaseHandler::RemoveFile(const std::string& searchAtt, const std::string& searchVal, const std::string& refdb )
351   {
352           
353           std::stringstream result;
354           std::string sel="SELECT PARENT_ID FROM FILES WHERE "+searchAtt+"='"+searchVal+"' AND REFERENCEDDB='"+refdb+"';";
355                 
356           CppSQLite3Query q;
357           QUERYTIMESTAMPDB(sel,q);
358         
359           while (!q.eof())
360           {
361             for (int fld = 0; fld < q.numFields(); fld++)
362               {
363                           result<<q.getStringField(fld);
364               }
365             q.nextRow();
366           }
367           DBRemove(searchAtt,searchVal,refdb);
368           
369                   int nChildren=0;
370                   sel="SELECT ID FROM FILES WHERE PARENT_ID='"+result.str()+"'";
371                   CppSQLite3Query q2;
372                   QUERYTIMESTAMPDB(sel,q2);
373                   while (!q2.eof())
374                         {
375                                 nChildren++;
376                                 q2.nextRow();
377                         }
378                         if(nChildren<1)
379                         {
380                                 if(!result.str().compare("0"))
381                                 {
382                                 RemoveFile("ID",result.str(),refdb);
383                                 }
384                                 else
385                                 {
386                                 DBRemove("ID",result.str(),refdb);
387                                 }
388                         }
389   }
390
391   //=====================================================================
392   void TimestampDatabaseHandler::DBRemove(const std::string& searchAtt, const std::string& searchVal, const std::string& refdb)
393   {
394        
395     std::string query = "DELETE FROM FILES WHERE "+searchAtt+"='"+ searchVal + "' AND REFERENCEDDB='"+refdb+"';";
396     UPDATETIMESTAMPDB(query);
397   }
398
399    //=====================================================================
400   bool TimestampDatabaseHandler::CheckTimestamp(const std::string pathId, const time_t lastModif, const std::string& refdb)
401   {
402         std::string sel="SELECT LastModified FROM FILES WHERE ID='"+pathId+"' AND REFERENCEDDB='"+refdb+"';";
403         CppSQLite3Query q;
404         QUERYTIMESTAMPDB(sel,q);
405         double timestamp;
406         
407         while (!q.eof())
408           {
409             for (int fld = 0; fld < q.numFields(); fld++)
410               {
411                           timestamp=q.getFloatField(fld);
412               }
413             q.nextRow();
414           }
415
416           
417           std::stringstream lm;
418           lm<<lastModif;
419           double modif=atof((lm.str()).c_str());
420           if(timestamp<modif)
421           {
422                   SetAttribute("LastModified",lm.str(),"ID",pathId);
423                   return true;
424           }
425           return false;  
426   }
427
428 }// namespace creaImageIO