]> Creatis software - creaImageIO.git/blob - src2/creaImageIOTimestampDatabaseHandler.cpp
Added functionality for non loaded nodes
[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 += ",\nconstraint FK_PARENT foreign key (PARENT_ID) references ";
173                 command += "FILES";
174                 command += "(ID) on delete restrict on update restrict";
175               
176             command += "\n)";
177             UPDATETIMESTAMPDB(command);
178             
179     return true;
180   }
181
182
183
184   //=====================================================================
185   void TimestampDatabaseHandler::CleanName(std::string& str) const
186   {
187          size_t pos;
188          do
189      {
190          pos = str.find('\\');
191          if (pos!=-1)  
192                  {
193                          str.replace(pos, 1, "/");
194                  }
195      }
196      while (pos!=-1);
197   }
198
199
200   //=====================================================================
201
202   bool TimestampDatabaseHandler::AddDirectory(const std::string& parent,
203                                                                                    const std::string& path, 
204                                                                                    const time_t lastModif, 
205                                                                                    const time_t lastRead)
206   {
207          bool valid=false;
208          std::string par=parent.c_str();
209          std::string pat=path.c_str();
210          CleanName(par);
211          CleanName(pat);
212
213          std::string pathId=IsIndexed(pat);
214          //Case: It is a root parent
215          if(parent.compare("")==0)
216          {
217                  if(pathId.compare("")==0)
218                  {
219                         AddFile(pat,lastModif,lastRead);
220                         valid=true;
221                  }
222                  else
223                  {
224                          valid=CheckTimestamp(pathId, lastModif);
225                  }
226          }
227          else 
228          {
229                  std::string parentId=IsIndexed(par);
230                  //Case: Parent is not in database
231                  if(parentId.compare("")==0)
232                 {
233                         AddFile(par,lastModif,lastRead);
234                         parentId=IsIndexed(par);
235                 }
236
237                 //Case path is not in database
238                 if(pathId.compare("")==0)
239                 {
240                     AddFile(parentId,pat,lastModif,lastRead);
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);
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)
257   {
258         std::stringstream out;
259         out<<"INSERT INTO FILES (PARENT_ID,PATH,LastModified,LastRead) VALUES(0,'"<<path<<"',";
260         out<<lastModif<<","<<lastRead<<");";
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   {
272         std::stringstream out;
273         out<<"INSERT INTO FILES (PARENT_ID,PATH,LastModified,LastRead) VALUES("<<parentId<<",'"<<path<<"',";
274         out<<lastModif<<","<<lastRead<<");";
275     UPDATETIMESTAMPDB(out.str());
276   }
277
278   //=====================================================================
279   std::string TimestampDatabaseHandler::IsIndexed(const std::string& path)
280   {
281         std::stringstream out;
282         std::stringstream result;
283         out<<"SELECT ID FROM FILES WHERE PATH='"<<path<<"'";
284                 
285         CppSQLite3Query q;
286         QUERYTIMESTAMPDB(out.str(),q);
287         
288         
289         while (!q.eof())
290           {
291             for (int fld = 0; fld < q.numFields(); fld++)
292               {
293                           result<<q.getStringField(fld);
294               }
295             q.nextRow();
296           }
297
298           return result.str();
299   }
300
301   //=====================================================================
302   void TimestampDatabaseHandler::SetAttribute(const std::string& attName, 
303                                                                                         const std::string& attValue,
304                                                                                         const std::string& searchParam,
305                                                                                         const std::string& searchValue)
306   {
307         std::string av=attValue.c_str();
308         std::string sv=searchValue.c_str();
309         CleanName(av);
310         CleanName(sv);
311
312         std::string sql = "UPDATE FILES SET ";
313     sql += attName;
314     sql += " = '";
315     sql += av;
316     sql += "' WHERE ";
317         sql += searchParam;
318         sql += " = '";
319     sql += sv;
320         sql += "'";
321     UPDATETIMESTAMPDB(sql);
322   }
323  
324   //=====================================================================
325   void TimestampDatabaseHandler::RemoveNode(const std::string& searchAtt, tree::Node* node)
326   {
327           int n=node->GetNumberOfChildren();
328           if(n>0)
329           {
330                   std::vector<tree::Node*> children=node->GetChildrenList();
331                   std::vector<tree::Node*>::iterator it;
332                   for(it=children.begin();it!=children.end();++it)
333                   {
334                           RemoveNode(searchAtt,(*it));
335                   }
336           }
337           else if(node->GetLevel()==3)
338           {
339                   RemoveFile(searchAtt,node->GetAttribute("FullFileName"));
340           }
341           else
342           {
343                   DBRemove("TopLevelNodeId",node->GetAttribute("ID"));
344           }
345
346
347   }
348   //=====================================================================
349   void TimestampDatabaseHandler::RemoveFile(const std::string& searchAtt, const std::string& searchVal)
350   {
351           
352           std::stringstream result;
353           std::string sel="SELECT PARENT_ID FROM FILES WHERE "+searchAtt+"='"+searchVal+"'";
354                 
355           CppSQLite3Query q;
356           QUERYTIMESTAMPDB(sel,q);
357         
358           while (!q.eof())
359           {
360             for (int fld = 0; fld < q.numFields(); fld++)
361               {
362                           result<<q.getStringField(fld);
363               }
364             q.nextRow();
365           }
366           DBRemove(searchAtt,searchVal);
367           
368                   int nChildren=0;
369                   sel="SELECT ID FROM FILES WHERE PARENT_ID='"+result.str()+"'";
370                   CppSQLite3Query q2;
371                   QUERYTIMESTAMPDB(sel,q2);
372                   while (!q2.eof())
373                         {
374                                 nChildren++;
375                                 q2.nextRow();
376                         }
377                         if(nChildren<1)
378                         {
379                                 if(!result.str().compare("0"))
380                                 {
381                                 RemoveFile("ID",result.str());
382                                 }
383                                 else
384                                 {
385                                 DBRemove("ID",result.str());
386                                 }
387                         }
388   }
389
390   //=====================================================================
391   void TimestampDatabaseHandler::DBRemove(const std::string& searchAtt, const std::string& searchVal)
392   {
393        
394     std::string query = "DELETE FROM FILES WHERE "+searchAtt+"='"+ searchVal + "';";
395     UPDATETIMESTAMPDB(query);
396   }
397
398    //=====================================================================
399   bool TimestampDatabaseHandler::CheckTimestamp(const std::string pathId, const time_t lastModif)
400   {
401         std::string sel="SELECT LastModified FROM FILES WHERE ID='"+pathId+"';";
402         CppSQLite3Query q;
403         QUERYTIMESTAMPDB(sel,q);
404         double timestamp;
405         
406         while (!q.eof())
407           {
408             for (int fld = 0; fld < q.numFields(); fld++)
409               {
410                           timestamp=q.getFloatField(fld);
411               }
412             q.nextRow();
413           }
414
415           
416           std::stringstream lm;
417           lm<<lastModif;
418           double modif=atof((lm.str()).c_str());
419           if(timestamp<modif)
420           {
421                   SetAttribute("LastModified",lm.str(),"ID",pathId);
422                   return true;
423           }
424           return false;  
425   }
426
427 }// namespace creaImageIO