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