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