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