]> Creatis software - creaImageIO.git/blob - src2/creaImageIOTreeHandlerImageAdder.cpp
22c727b87d83ae02b21b47dbff5e85d6646baa66
[creaImageIO.git] / src2 / creaImageIOTreeHandlerImageAdder.cpp
1 #include <creaImageIOTreeHandlerImageAdder.h>
2 #include <creaImageIOSystem.h>
3 #include "boost/filesystem.hpp"
4 #include <boost/filesystem/operations.hpp>
5 #include <boost/utility.hpp>
6
7
8 namespace fs = boost::filesystem;
9 using boost::filesystem::path;
10 using boost::next;
11 using boost::prior;
12
13
14 using namespace crea;
15
16 namespace creaImageIO
17 {
18   //====================================================================
19   // Ctor
20   TreeHandlerImageAdder::TreeHandlerImageAdder(TreeHandler* tree)
21     : mTreeHandler(tree)
22   {
23   }
24   // Dtor
25   TreeHandlerImageAdder::~TreeHandlerImageAdder()
26   {
27   }
28   //====================================================================
29
30   //====================================================================
31   void TreeHandlerImageAdder::ConnectProgressObserver(ProgressCallbackType callback)
32   {
33     mProgressSignal.connect(callback);
34   }
35   //====================================================================
36
37   //=====================================================================
38   bool TreeHandlerImageAdder::IsHandledFile( const std::string& filename)
39   {
40     return (mReader.CanRead(filename));
41   }
42   //=====================================================================
43
44   //=====================================================================
45   void TreeHandlerImageAdder::AddFiles( const std::vector<std::string>& filenames)
46   {
47     mProgress.Reset();
48         
49     unsigned int nbf = filenames.size(); 
50     std::vector<std::string>::const_iterator i;
51     for (i=filenames.begin();i!=filenames.end();++i)
52       {
53         mTimestampHandler->AddFile((*i), fs::last_write_time(*i), time(0));
54         mProgress.IncNumberScannedFiles();
55         if (IsHandledFile(*i)) 
56           {
57             mProgress.IncNumberHandledFiles();
58                 mSynchronizer->InsertAddOp((*i),"0","1");
59                 std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","ADD_OPS","PATH",(*i));
60                 std::stringstream removedOn;
61                 removedOn<<time(0);
62                 mSynchronizer->InsertIgnoreFile(addKey,(*i),"0",removedOn.str());
63             AddFile(*i);
64           }
65         mProgressSignal(mProgress);
66         if (mProgress.GetStop()) break;
67       }
68   }
69   //=====================================================================
70
71   //=====================================================================
72   void TreeHandlerImageAdder::AddDirectory( const std::string& directory,
73                                             bool recurse)
74   {
75     mProgress.Reset();
76         std::stringstream files;
77         
78         std::stringstream rec;
79         rec<<recurse;
80         mSynchronizer->InsertAddOp(directory,rec.str(),"0");
81         std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","ADD_OPS","PATH",directory);
82         AddDirectoryRecursor( directory, recurse, addKey );
83         
84         int nFiles=GetProgress().GetNumberAddedFiles();
85         files<<nFiles;
86         mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",files.str(),"ADD_KEY",addKey);
87     GimmickDebugMessage(3,mProgress<<std::endl);
88   }
89
90   //=====================================================================
91   void TreeHandlerImageAdder::AddFile( const std::string& filename )
92   {
93     GimmickDebugMessage(4,"Adding '"<<filename<<"'"<<std::endl);
94     std::map< std::string, std::string>  attr;
95     mTreeHandler->GetTree().GetDescriptor().BuildAttributeMap(attr);
96
97     mReader.ReadAttributes(filename,attr);
98
99     int lev = mTreeHandler->AddBranch(attr);
100
101     // update the progress according to lev
102     if (lev<mTreeHandler->GetTree().GetNumberOfLevels())
103       mProgress.IncNumberAddedFiles();
104   }
105   //=====================================================================
106
107   void TreeHandlerImageAdder::RemoveFile( tree::Node* node)
108   {
109                 int n=node->GetNumberOfChildren();
110                 if(n>0)
111                 {
112                         RemoveFiles(node->GetChildrenList());
113                 }
114                 else
115                 {
116                   std::string path=node->GetAttribute("FullFileName");
117                   //Gets the add key
118                   std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","IGNORED_FILES","PATH",path);
119                   //Gets the number of files added
120                   int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",addKey)).c_str());
121                   files=files-1;
122                   std::stringstream out;
123                   out<<files;
124                   //Sets the new number of files
125                   mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",out.str(),"ADD_KEY",addKey);
126                   //Sets the file as removed
127                   mSynchronizer->SetAttribute("REMOVE","IGNORED_FILES","1","PATH",path);
128                 }
129   }
130
131   //=====================================================================
132
133   void TreeHandlerImageAdder::RemoveFiles(const std::vector<tree::Node*>& nodes)
134   {
135           std::vector<tree::Node*>::const_iterator it;
136           for(it=nodes.begin();it!=nodes.end();++it)
137           {
138                 int n=(*it)->GetNumberOfChildren();
139                 if(n>0)
140                 {
141                         RemoveFiles((*it)->GetChildrenList());
142                 }
143                 else
144                 {
145                    std::string path=(*it)->GetAttribute("FullFileName");
146                   //Gets the add key
147                   std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","IGNORED_FILES","PATH",path);
148                   //Gets the number of files added
149                   int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",addKey)).c_str());
150                   files=files-1;
151                   std::stringstream out;
152                   out<<files;
153                   //Sets the new number of files
154                   mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",out.str(),"ADD_KEY",addKey);
155                   //Sets the file as removed
156                   mSynchronizer->SetAttribute("REMOVE","IGNORED_FILES","1","PATH",path);
157                 }
158         
159           }
160   }
161
162   //=====================================================================
163   void TreeHandlerImageAdder::AddDirectoryRecursor(const std::string &dirpath, 
164                                                    bool recursive,
165                                                    const std::string &addKey)
166   {
167     GimmickDebugMessage(4,"Scanning '"<<dirpath<<"'"<<std::endl);
168     mProgress.IncNumberScannedDirs();
169
170     if ( !fs::exists( dirpath ) ) return;
171         time_t lastModif=fs::last_write_time(dirpath);
172
173     fs::directory_iterator end_itr; // default construction yields past-the-end
174     for ( fs::directory_iterator itr( dirpath );
175           itr != end_itr;
176           ++itr )
177       {
178         // If is directory & recurse : do recurse
179         if ( fs::is_directory(itr->status()) )
180           {
181             if (recursive) 
182                 {
183                         AddDirectoryRecursor( itr->string(), recursive, addKey);
184                 }
185           }
186         else 
187           {
188                 std::string parent_id;
189                 bool valid=mTimestampHandler->AddDirectory(dirpath, itr->string(), lastModif, time(0));
190                 if(valid)
191                 {
192                         mProgress.IncNumberScannedFiles();
193                         if (IsHandledFile(itr->string()))
194                         {
195                         mProgress.IncNumberHandledFiles();
196                         AddFile( itr->string() );
197                         mTreeHandler->GetTopLevelNodeId("FullFileName",itr->string(),parent_id);
198                         mTimestampHandler->SetAttribute("TopLevelNodeId",parent_id,"PATH",itr->string());
199                         std::stringstream removedOn;
200                         removedOn<<time(0);
201                         mSynchronizer->InsertIgnoreFile(addKey, itr->string(),"0",removedOn.str());
202                         }
203                         mProgressSignal(mProgress);
204                         if (mProgress.GetStop()) 
205                         {
206                         //itr = end_itr;
207                         break;
208                         }
209                 }
210                 mTimestampHandler->SetAttribute("TopLevelNodeId",parent_id,"PATH",dirpath);
211           }
212       }
213         
214   }
215   //=======================================================================
216   
217   //=======================================================================
218
219   void TreeHandlerImageAdder::CheckSyncDirectory(const std::string &dirpath, 
220                                                                                                 bool recursive, 
221                                                                                                 bool repair,
222                                                                                                 bool checkAttributes,
223                                                                                                 std::vector<std::string> &i_ignorefiles,
224                                                                                                 std::vector<std::string> & attsModified,
225                                                                                                 std::vector<std::string> & newfiles)
226   {
227     if ( !fs::exists( dirpath ) ) return;
228     fs::directory_iterator end_itr; // default construction yields past-the-end
229                           
230     for ( fs::directory_iterator itr( dirpath ); itr != end_itr; ++itr ) 
231         {
232         // If is directory & recurse : do recurse
233         if ( fs::is_directory(itr->status()) )
234         {
235             if (recursive)
236                         {
237                 CheckSyncDirectory( itr->string(), recursive, repair, checkAttributes, i_ignorefiles, attsModified, newfiles);
238                         }
239         }
240         else
241         {
242             if (IsHandledFile(itr->string()))
243             {
244                 bool bfound = false;
245                 for(std::vector<std::string>::iterator it_new = i_ignorefiles.begin(); it_new < i_ignorefiles.end(); ++it_new)
246                 {
247                                         if((*it_new) == itr->string())
248                     {
249                         bfound = true;
250                                                 //Additional checking of attributes
251                                                 if(checkAttributes)
252                                                 {
253                                                         CheckAttributes(repair,(*it_new),attsModified);
254                                                 }
255                         i_ignorefiles.erase(it_new);
256                         break;
257                     }
258                                 }
259                                 if(!bfound && i_ignorefiles.size()>0 )
260                 {
261                     newfiles.push_back( itr->string() );
262                 }
263                         }
264                 }
265          }
266   } 
267
268   //=======================================================================
269   
270   //=======================================================================
271
272   std::string TreeHandlerImageAdder::Synchronize(bool repair, bool checkAttributes)
273   {
274           std::vector<AddList> fileList;
275           std::vector<std::string> ignoreList;
276           std::vector<std::string> newFiles;
277           std::vector<std::string> attsModified;
278           std::stringstream mess;
279           std::vector<AddList>::iterator iter;
280
281           //Gets the list of added files
282           mSynchronizer->GetFileList(fileList);
283
284           std::vector<std::string>::iterator i;
285           //Actions to take if the user doesn't want to repair
286           if(!repair)
287           {
288                 //Iterates to see if they are in sync
289                 for(iter=fileList.begin();iter!=fileList.end();++iter)
290                 {
291                         mSynchronizer->GetIgnoredFiles((*iter).key,ignoreList);
292                         bool rec=true;
293                         if((*iter).recursive=="0"){rec=false;}
294                         CheckSyncDirectory((*iter).path,rec,repair,checkAttributes,ignoreList,attsModified,newFiles);
295                 }
296
297                 //Add to message the result of new found files
298                 mess<<"New Files Found: "<<newFiles.size()<<std::endl;
299                 if(newFiles.size()>0)
300                 {
301                         mess<<"Filenames: "<<std::endl;
302                         for(i=newFiles.begin();i!=newFiles.end();++i)
303                         {
304                                 mess<<*i<<std::endl;
305                         }
306                 }
307
308                 //Add to message the result of missing files
309                 mess<<"Missing Files: "<<ignoreList.size()<<std::endl;
310                 if(ignoreList.size()>0)
311                 {
312                         mess<<"Filenames: "<<std::endl;
313                         for(i=ignoreList.begin();i!=ignoreList.end();++i)
314                         {
315                                 mess<<*i<<std::endl;
316                         }
317                 }
318
319                 //In the case that the user wants to check the attributes...
320                 if(checkAttributes)
321                 {
322                         //... add to message the result of files that have been changed.
323                         mess<<"Files with different attributes: "<<attsModified.size()<<std::endl;
324                         if(attsModified.size()>0)
325                         {
326                                 mess<<"Filenames: "<<std::endl;
327                                 for(i=attsModified.begin();i!=attsModified.end();++i)
328                                 {
329                                         mess<<*i<<std::endl;
330                                 }
331                         }
332                 }
333                 
334           }
335
336           //Actions to take if the user wants to repair
337           else
338           {
339                   int nf=0;
340                 //Iterates to see if they are in sync
341                 for(iter=fileList.begin();iter!=fileList.end();++iter)
342                 {
343                         mSynchronizer->GetIgnoredFiles((*iter).key,ignoreList);
344                         bool rec=true;
345                         if((*iter).recursive=="0"){rec=false;}
346                         CheckSyncDirectory((*iter).path,rec,repair,checkAttributes,ignoreList,attsModified,newFiles);
347
348                         //For the new files, add them
349                         for (i=newFiles.begin();i!=newFiles.end();++i)
350                         {
351                         mTimestampHandler->AddFile((*i), fs::last_write_time(*i), time(0));
352                         if (IsHandledFile(*i)) 
353                         {
354                                 std::stringstream removedOn;
355                                 removedOn<<time(0);
356                                 mSynchronizer->InsertIgnoreFile((*iter).key,(*i),"0",removedOn.str());
357                                 //Gets the number of files added
358                                 int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",(*iter).key)).c_str());
359                                 files=files+1;
360                                 std::stringstream out;
361                                 out<<files;
362                                 //Sets the new number of files
363                                 mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",out.str(),"ADD_KEY",(*iter).key);
364                                 AddFile(*i);
365                         }
366                         }
367                         nf+=newFiles.size();
368                         newFiles.clear();
369
370                 }
371                 //Reports number of added files
372                 mess<<"Files Added: "<<nf<<std::endl;
373                 
374                 //Removes the necessary files and reports the results
375                 if(ignoreList.size()>0)
376                 {
377                         tree::Node* node;
378                         mTreeHandler->LoadChildren(NULL,4);
379                         for(i=ignoreList.begin();i!=ignoreList.end();++i)
380                         {
381                                 FindNode(mTreeHandler->GetTree().GetChildrenList()[0],3,"FullFileName",*i,node);
382                                 RemoveFile(node);
383                                 mTreeHandler->Remove(node);
384                         }
385                 }
386                 mess<<"Files Removed: "<<ignoreList.size()<<std::endl;
387                 //In the case that the user wants to check the attributes...
388                 if(checkAttributes)
389                 {
390                         //... add to message the result of files that were modified.
391                         mess<<"Files Modified: "<<attsModified.size()<<std::endl;
392                 }
393           }
394           return mess.str();
395
396   }
397   //=======================================================================
398
399   void TreeHandlerImageAdder::CheckAttributes(bool repair, std::string& file, std::vector<std::string>& attsModified)
400   {
401           std::map< std::string, std::string>  attr;
402           mTreeHandler->GetTree().GetDescriptor().BuildAttributeMap(attr);
403       mReader.ReadAttributes(file,attr);
404           tree::LevelDescriptor::AttributeDescriptorListType adl= mTreeHandler->GetTree().GetAttributeDescriptorList(mTreeHandler->GetTree().GetNumberOfLevels()-1);    
405           tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a;
406           for (a = adl.begin();a!=adl.end();++a)
407           {
408            std::string databaseVal;
409            mTreeHandler->GetAttribute("Image","FullFileName",file,a->GetKey(),databaseVal);
410            std::string fileVal=attr.find(a->GetKey())->second;
411            if ( a->GetFlags()==0 && databaseVal.compare(fileVal)!=0 ) 
412             {
413                         if(repair)
414                         {
415                                 mTreeHandler->SetAttribute("Image",a->GetKey(),fileVal,"FullFileName", file);   
416                         }
417                         attsModified.push_back(file);
418             }
419                 
420           }
421           
422   }
423
424   //=======================================================================
425
426
427   void TreeHandlerImageAdder::FindNode(tree::Node* parent, int level, const std::string& searchParam, const std::string& searchVal, tree::Node*& node)
428   {
429           if(level>1)
430           {
431                   std::vector<tree::Node*>::iterator iter;
432                   for(iter=parent->GetChildrenList().begin();iter!=parent->GetChildrenList().end();++iter)
433                   {
434                           FindNode(*iter,level-1,searchParam,searchVal,node);
435                   }
436           }
437           else
438           {
439                   if(parent->GetAttribute(searchParam).compare(searchVal)==0)
440                   {
441                           node=parent;
442                   }
443
444           }
445   }
446   
447   //=======================================================================
448
449
450  
451 }