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