]> Creatis software - creaImageIO.git/blob - src2/creaImageIOTreeHandlerImageAdder.cpp
b1a60437cd2fa22737e4f1bd0b0fd2e339c4a273
[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         
54         mProgress.IncNumberScannedFiles();
55         if (IsHandledFile(*i)) 
56           {
57             mProgress.IncNumberHandledFiles();
58                 mSynchronizer->InsertAddOp((*i),"0","1",mCurrentDB);
59                 std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","ADD_OPS","PATH",(*i),mCurrentDB);
60                 std::stringstream removedOn;
61                 removedOn<<time(0);
62                 mSynchronizer->InsertIgnoreFile(addKey,(*i),"0",removedOn.str(),mCurrentDB);
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",mCurrentDB);
81         std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","ADD_OPS","PATH",directory,mCurrentDB);
82         mTreeHandler->BeginTransaction();
83         mSynchronizer->GetList();
84         AddDirectoryRecursor( directory, recurse, addKey );
85         
86         int nFiles=GetProgress().GetNumberAddedFiles();
87         files<<nFiles;
88         mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",files.str(),"ADD_KEY",addKey,mCurrentDB);
89         mTreeHandler->EndTransaction();
90     GimmickDebugMessage(3,mProgress<<std::endl);
91   }
92
93   //=====================================================================
94   void TreeHandlerImageAdder::AddFile( const std::string& filename )
95   {
96     GimmickDebugMessage(4,"Adding '"<<filename<<"'"<<std::endl);
97     std::map< std::string, std::string>  attr;
98     mTreeHandler->GetTree().GetDescriptor().BuildAttributeMap(attr);
99
100     mReader.ReadAttributes(filename,attr);
101
102     int lev = mTreeHandler->AddBranch(attr);
103
104     // update the progress according to lev
105     if (lev<mTreeHandler->GetTree().GetNumberOfLevels())
106       mProgress.IncNumberAddedFiles();
107   }
108   //=====================================================================
109
110   void TreeHandlerImageAdder::RemoveFile( tree::Node* node)
111   {
112                 int n=node->GetNumberOfChildren();
113                 if(n>0)
114                 {
115                         RemoveFiles(node->GetChildrenList());
116                 }
117                 else
118                 {
119                   std::string path=node->GetAttribute("FullFileName");
120                   //Gets the add key
121                   std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","IGNORED_FILES","PATH",path,mCurrentDB);
122                   //Gets the number of files added
123                   int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",addKey,mCurrentDB)).c_str());
124                   files=files-1;
125                   std::stringstream out;
126                   out<<files;
127                   //Sets the new number of files
128                   mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",out.str(),"ADD_KEY",addKey,mCurrentDB);
129                   //Sets the file as removed
130                   mSynchronizer->SetAttribute("REMOVE","IGNORED_FILES","1","PATH = '"+path+"' AND ADD_KEY",addKey,mCurrentDB);
131                 }
132   }
133
134   //=====================================================================
135
136   void TreeHandlerImageAdder::RemoveFiles(const std::vector<tree::Node*>& nodes)
137   {
138           std::vector<tree::Node*>::const_iterator it;
139           for(it=nodes.begin();it!=nodes.end();++it)
140           {
141                 int n=(*it)->GetNumberOfChildren();
142                 if(n>0)
143                 {
144                         RemoveFiles((*it)->GetChildrenList());
145                 }
146                 else
147                 {
148                    std::string path=(*it)->GetAttribute("FullFileName");
149                   //Gets the add key
150                   std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","IGNORED_FILES","PATH",path,mCurrentDB);
151                   //Gets the number of files added
152                   int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",addKey,mCurrentDB)).c_str());
153                   files=files-1;
154                   std::stringstream out;
155                   out<<files;
156                   //Sets the new number of files
157                   mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",out.str(),"ADD_KEY",addKey,mCurrentDB);
158                   //Sets the file as removed
159                   mSynchronizer->SetAttribute("REMOVE","IGNORED_FILES","1","PATH = '"+path+"' AND ADD_KEY",addKey,mCurrentDB);
160                 }
161         
162           }
163   }
164
165  
166   //=====================================================================
167   void TreeHandlerImageAdder::AddDirectoryRecursor(const std::string &dirpath, 
168                                                    bool recursive,
169                                                    const std::string &addKey)
170   {
171     GimmickDebugMessage(4,"Scanning '"<<dirpath<<"'"<<std::endl);
172     mProgress.IncNumberScannedDirs();
173
174     if ( !fs::exists( dirpath ) ) return;
175         time_t lastModif=fs::last_write_time(dirpath);
176
177         
178     fs::directory_iterator end_itr; // default construction yields past-the-end
179     for ( fs::directory_iterator itr( dirpath );
180           itr != end_itr;
181           ++itr )
182         {
183         // If is directory & recurse : do recurse
184         if ( fs::is_directory(itr->status()) )
185           {
186             if (recursive) 
187                 {
188                         AddDirectoryRecursor( itr->string(), recursive, addKey);
189                 }
190           }
191         else 
192           {
193                 std::string parent_id;
194                 // tTest if directory (and only it) exists or not.
195                 bool valid = mSynchronizer->isIndexed(itr->string());//true;//=mTimestampHandler->AddDirectory(dirpath, itr->string(), lastModif, time(0),mCurrentDB);
196                 if(valid)
197                 {
198                         mProgress.IncNumberScannedFiles();
199                         if (IsHandledFile(itr->string()))
200                         {
201                         mProgress.IncNumberHandledFiles();
202                         AddFile( itr->string() );
203                         mTreeHandler->GetTopLevelNodeId("FullFileName",itr->string(),parent_id);
204                         std::stringstream removedOn;
205                         removedOn<<time(0);
206                         mSynchronizer->InsertIgnoreFile(addKey, itr->string(),"0",removedOn.str(),mCurrentDB);
207                         }
208                         
209                         mProgressSignal(mProgress);
210                         if (mProgress.GetStop()) 
211                         {
212                         //itr = end_itr;
213                         break;
214                         }
215                         
216                 }
217           }
218       }
219         
220   }
221   //=======================================================================
222   
223   //=======================================================================
224
225   void TreeHandlerImageAdder::CheckSyncDirectory(const std::string &dirpath, 
226                                                                                                 bool recursive, 
227                                                                                                 bool repair,
228                                                                                                 bool checkAttributes,
229                                                                                                 std::vector<std::string> &i_ignorefiles,
230                                                                                                 std::vector<std::string> & attsModified,
231                                                                                                 std::vector<std::string> & newfiles)
232   {
233     if ( !fs::exists( dirpath ) ) return;
234     fs::directory_iterator end_itr; // default construction yields past-the-end
235                           
236     for ( fs::directory_iterator itr( dirpath ); itr != end_itr; ++itr ) 
237         {
238         // If is directory & recurse : do recurse
239         if ( fs::is_directory(itr->status()) )
240         {
241             if (recursive)
242                         {
243                 CheckSyncDirectory( itr->string(), recursive, repair, checkAttributes, i_ignorefiles, attsModified, newfiles);
244                         }
245         }
246         else
247         {
248             if (IsHandledFile(itr->string()))
249             {
250                 bool bfound = false;
251                 for(std::vector<std::string>::iterator it_new = i_ignorefiles.begin(); it_new < i_ignorefiles.end(); ++it_new)
252                 {
253                                         if((*it_new) == itr->string())
254                     {
255                         bfound = true;
256                                                 //Additional checking of attributes
257                                                 if(checkAttributes)
258                                                 {
259                                                         CheckAttributes(repair,(*it_new),attsModified);
260                                                 }
261                         i_ignorefiles.erase(it_new);
262                         break;
263                     }
264                                 }
265                                 if(!bfound && i_ignorefiles.size()>0 )
266                 {
267                     newfiles.push_back( itr->string() );
268                 }
269                         }
270                 }
271          }
272   } 
273
274   //=======================================================================
275   
276   //=======================================================================
277
278   std::string TreeHandlerImageAdder::Synchronize(bool repair, bool checkAttributes)
279   {
280           std::vector<AddList> fileList;
281           std::vector<std::string> ignoreList;
282           std::vector<std::string> newFiles;
283           std::vector<std::string> attsModified;
284           std::stringstream mess;
285           std::vector<AddList>::iterator iter;
286
287           //Gets the list of added files
288           mSynchronizer->GetFileList(fileList,mCurrentDB);
289
290           std::vector<std::string>::iterator i;
291           //Actions to take if the user doesn't want to repair
292           if(!repair)
293           {
294                 //Iterates to see if they are in sync
295                 for(iter=fileList.begin();iter!=fileList.end();++iter)
296                 {
297                         mSynchronizer->GetIgnoredFiles((*iter).key,ignoreList);
298                         bool rec=true;
299                         if((*iter).recursive=="0"){rec=false;}
300                         CheckSyncDirectory((*iter).path,rec,repair,checkAttributes,ignoreList,attsModified,newFiles);
301                 }
302
303                 //Add to message the result of new found files
304                 mess<<"New Files Found: "<<newFiles.size()<<std::endl;
305                 if(newFiles.size()>0)
306                 {
307                         mess<<"Filenames: "<<std::endl;
308                         for(i=newFiles.begin();i!=newFiles.end();++i)
309                         {
310                                 mess<<*i<<std::endl;
311                         }
312                 }
313
314                 //Add to message the result of missing files
315                 mess<<"Missing Files: "<<ignoreList.size()<<std::endl;
316                 if(ignoreList.size()>0)
317                 {
318                         mess<<"Filenames: "<<std::endl;
319                         for(i=ignoreList.begin();i!=ignoreList.end();++i)
320                         {
321                                 mess<<*i<<std::endl;
322                         }
323                 }
324
325                 //In the case that the user wants to check the attributes...
326                 if(checkAttributes)
327                 {
328                         //... add to message the result of files that have been changed.
329                         mess<<"Files with different attributes: "<<attsModified.size()<<std::endl;
330                         if(attsModified.size()>0)
331                         {
332                                 mess<<"Filenames: "<<std::endl;
333                                 for(i=attsModified.begin();i!=attsModified.end();++i)
334                                 {
335                                         mess<<*i<<std::endl;
336                                 }
337                         }
338                 }
339                 
340           }
341
342           //Actions to take if the user wants to repair
343           else
344           {
345                   int nf=0;
346                 //Iterates to see if they are in sync
347                 for(iter=fileList.begin();iter!=fileList.end();++iter)
348                 {
349                         mSynchronizer->GetIgnoredFiles((*iter).key,ignoreList);
350                         bool rec=true;
351                         if((*iter).recursive=="0"){rec=false;}
352                         CheckSyncDirectory((*iter).path,rec,repair,checkAttributes,ignoreList,attsModified,newFiles);
353
354                         //For the new files, add them
355                         for (i=newFiles.begin();i!=newFiles.end();++i)
356                         {
357                         if (IsHandledFile(*i)) 
358                         {
359                                 std::stringstream removedOn;
360                                 removedOn<<time(0);
361                                 mSynchronizer->InsertIgnoreFile((*iter).key,(*i),"0",removedOn.str(),mCurrentDB);
362                                 //Gets the number of files added
363                                 int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",(*iter).key,mCurrentDB)).c_str());
364                                 files=files+1;
365                                 std::stringstream out;
366                                 out<<files;
367                                 //Sets the new number of files
368                                 mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",out.str(),"ADD_KEY",(*iter).key,mCurrentDB);
369                                 AddFile(*i);
370                         }
371                         }
372                         nf+=newFiles.size();
373                         newFiles.clear();
374
375                 }
376                 //Reports number of added files
377                 mess<<"Files Added: "<<nf<<std::endl;
378                 
379                 //Removes the necessary files and reports the results
380                 if(ignoreList.size()>0)
381                 {
382                         tree::Node* node;
383                         mTreeHandler->LoadChildren(NULL,4);
384                         for(i=ignoreList.begin();i!=ignoreList.end();++i)
385                         {
386                                 FindNode(mTreeHandler->GetTree().GetChildrenList()[0],3,"FullFileName",*i,node);
387                                 RemoveFile(node);
388                                 mTreeHandler->Remove(node);
389                         }
390                 }
391                 mess<<"Files Removed: "<<ignoreList.size()<<std::endl;
392                 //In the case that the user wants to check the attributes...
393                 if(checkAttributes)
394                 {
395                         //... add to message the result of files that were modified.
396                         mess<<"Files Modified: "<<attsModified.size()<<std::endl;
397                 }
398           }
399           return mess.str();
400
401   }
402   //=======================================================================
403
404   void TreeHandlerImageAdder::CheckAttributes(bool repair, std::string& file, std::vector<std::string>& attsModified)
405   {
406           std::map< std::string, std::string>  attr;
407           mTreeHandler->GetTree().GetDescriptor().BuildAttributeMap(attr);
408       mReader.ReadAttributes(file,attr);
409           tree::LevelDescriptor::AttributeDescriptorListType adl= mTreeHandler->GetTree().GetAttributeDescriptorList(mTreeHandler->GetTree().GetNumberOfLevels()-1);    
410           tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a;
411           for (a = adl.begin();a!=adl.end();++a)
412           {
413            std::string databaseVal;
414            mTreeHandler->GetAttribute("Image","FullFileName",file,a->GetKey(),databaseVal);
415            std::string fileVal=attr.find(a->GetKey())->second;
416            if ( a->GetFlags()==0 && databaseVal == fileVal) 
417             {
418                         if(repair)
419                         {
420                                 mTreeHandler->SetAttribute("Image",a->GetKey(),fileVal,"FullFileName", file);   
421                         }
422                         attsModified.push_back(file);
423             }
424                 
425           }
426           
427   }
428
429   //=======================================================================
430
431
432   void TreeHandlerImageAdder::FindNode(tree::Node* parent, int level, const std::string& searchParam, const std::string& searchVal, tree::Node*& node)
433   {
434           if(level>1)
435           {
436                   std::vector<tree::Node*>::iterator iter;
437                   for(iter=parent->GetChildrenList().begin();iter!=parent->GetChildrenList().end();++iter)
438                   {
439                           FindNode(*iter,level-1,searchParam,searchVal,node);
440                   }
441           }
442           else
443           {
444                   if(parent->GetAttribute(searchParam).compare(searchVal)==0)
445                   {
446                           node=parent;
447                   }
448
449           }
450   }
451   
452   void TreeHandlerImageAdder::SaveAs(const std::vector<std::string>& filenames, std::vector<vtkImageData *> i_images)
453   {
454           std::vector<std::string>::const_iterator it_file = filenames.begin();
455           std::vector<vtkImageData *>::iterator it_image = i_images.begin();
456         /*  mWriter.CanWrite(".jpeg");
457           for(; it_file != filenames.end(); ++it_file, ++it_image)
458                   mWriter.WriteImage(it_file->c_str(), (vtkImageData &)it_image);*/
459   }
460
461   //=======================================================================
462   void TreeHandlerImageAdder::FindNodePartial(tree::Node* parent, int level, const std::string& searchParam, const std::string& searchVal, tree::Node*& node)
463   {
464           if(level>1)
465           {
466                   std::vector<tree::Node*>::iterator iter;
467                   for(iter=parent->GetChildrenList().begin();iter!=parent->GetChildrenList().end() && node==0 ;++iter)
468                   {
469                           FindNodePartial(*iter,level-1,searchParam,searchVal,node);
470                   }
471           }
472           else
473           {
474                   if(parent->GetAttribute(searchParam).find(searchVal)<9000)
475                   {
476                           node=parent;
477                           return;
478                   }
479
480           }
481   }
482   
483   //=======================================================================
484
485   void TreeHandlerImageAdder::CopyFiles(const std::vector<std::string>& filenames, const std::string directory  )
486   {
487           std::vector<std::string>::const_iterator i;
488           if(!boost::filesystem::exists(directory))
489           {
490           boost::filesystem::create_directory(boost::filesystem::path(directory));
491           mSynchronizer->InsertAddOp(directory,"0","0",mCurrentDB);
492           }
493           std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","ADD_OPS","PATH",directory,mCurrentDB);
494           size_t last;
495           std::vector<std::string> newNames;
496           for(i=filenames.begin();i!=filenames.end();++i)
497           {
498                   std::string dir=directory.c_str();
499                   if(boost::filesystem::exists(*i) && (*i).find(dir)==std::string::npos)
500                   {
501                   std::string path=*i;
502                   last=(*i).find_last_of('/');
503                   std::string f="\\"+(*i).substr(last+1);
504         
505                   int p=1;
506                   std::stringstream out;
507                   out<<directory<<f;
508                   while(boost::filesystem::exists(out.str()))
509                   {
510                           out.str("");
511                           out<<directory<<f.substr(0,f.size()-4)<<"("<<p<<")"<<f.substr(f.size()-4);
512                           p++;
513                   }
514                   std::string result=out.str();
515                   boost::filesystem::copy_file((*i),result);
516
517                   //To update image database
518                   mTreeHandler->SetAttribute("Image","FullFileName",result,"FullFileName", (*i));
519                   
520                   //To update maintenance database
521                   //1.Add the new path and increase number of children on new operation.
522                   std::stringstream removedOn;
523                   removedOn<<time(0);
524                   //Inserts the file
525                   mSynchronizer->InsertIgnoreFile(addKey, result,"0",removedOn.str(),mCurrentDB);
526                   //Gets the number of files added
527                   int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",addKey,mCurrentDB)).c_str());
528                   files=files+1;
529                   std::stringstream fil;
530                   fil<<files;
531                   //Sets the new number of files
532                   mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",fil.str(),"ADD_KEY",addKey,mCurrentDB);
533                   fil.str("");
534
535                   //2.Set the old path as removed and decrease number of children on old operation.
536                   //Gets the old add key
537                   std::string oldAddKey=mSynchronizer->GetAttribute("ADD_KEY","IGNORED_FILES","PATH",path,mCurrentDB);
538                   //Sets the file as removed
539                   mSynchronizer->SetAttribute("REMOVE","IGNORED_FILES","1","PATH = '"+path+"' AND ADD_KEY",oldAddKey,mCurrentDB);
540                   //Gets the number of files added
541                   files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",oldAddKey,mCurrentDB)).c_str());
542                   files=files-1;
543                   fil<<files;
544                   //Sets the new number of files
545                   mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",fil.str(),"ADD_KEY",oldAddKey,mCurrentDB);
546                   
547                   }
548
549           }
550   }
551
552   //=======================================================================
553
554   void TreeHandlerImageAdder::DeleteDriveFromMainDB(const std::string& drive)
555   {
556           //Delete from local database and others
557           tree::Node* node=0;
558           mTreeHandler->LoadChildren(NULL,4);
559           FindNodePartial(mTreeHandler->GetTree().GetChildrenList()[0],3,"FullFileName",drive,node);
560           while(node!=0)
561           {
562           mTreeHandler->Remove(node);
563           node=0;
564           mTreeHandler->LoadChildren(NULL,4);
565           FindNodePartial(mTreeHandler->GetTree().GetChildrenList()[0],3,"FullFileName",drive,node); 
566           }
567   }
568
569    //=======================================================================
570
571   void TreeHandlerImageAdder::DeleteDriveFromOtherDB(const std::string& drive)
572   {
573           //Delete from maintenance
574           mSynchronizer->RemoveEntries("ADD_OPS", "PATH", "LIKE", drive+"%");
575           mSynchronizer->RemoveEntries("IGNORED_FILES", "PATH", "LIKE", drive+"%");
576   }
577
578   //=======================================================================
579   void TreeHandlerImageAdder::EditField(tree::Node* node, const std::string& name, const std::string& key, const std::string& val)
580   {
581           node->SetAttribute(key,val);
582           mTreeHandler->SetAttribute(node,key,val);
583   }
584
585   //=======================================================================
586   void TreeHandlerImageAdder::GetAttributes(const std::vector<std::string>& params, 
587           const std::string& filename, 
588           std::vector<std::string>& results)
589   {
590           std::vector<std::string>::const_iterator i;
591           std::string result;
592           for(i=params.begin();i!=params.end();i++)
593           {
594                   mTreeHandler->GetAttribute("Image","FullFileName",filename,*i,result);
595                   results.push_back(result);
596           }
597   }
598
599  
600 }