2 # ---------------------------------------------------------------------
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
10 # This software is governed by the CeCILL-B license under French law and
11 # abiding by the rules of distribution of free software. You can use,
12 # modify and/ or redistribute the software under the terms of the CeCILL-B
13 # license as circulated by CEA, CNRS and INRIA at the following URL
14 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15 # or in the file LICENSE.txt.
17 # As a counterpart to the access to the source code and rights to copy,
18 # modify and redistribute granted by the license, users are provided only
19 # with a limited warranty and the software's author, the holder of the
20 # economic rights, and the successive licensors have only limited
23 # The fact that you are presently reading this means that you have had
24 # knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------
28 #include <creaImageIOTreeHandlerImageAdder.h>
29 #include <creaImageIOSystem.h>
30 #include <boost/filesystem.hpp>
31 #include <boost/algorithm/string.hpp>
32 #include <boost/utility.hpp>
35 namespace fs = boost::filesystem;
36 using boost::filesystem::path;
42 using namespace boost;
46 //====================================================================
48 TreeHandlerImageAdder::TreeHandlerImageAdder(TreeHandler* tree)
53 TreeHandlerImageAdder::~TreeHandlerImageAdder()
56 //====================================================================
58 //====================================================================
59 void TreeHandlerImageAdder::ConnectProgressObserver(ProgressCallbackType callback)
61 mProgressSignal.connect(callback);
63 //====================================================================
65 //=====================================================================
66 bool TreeHandlerImageAdder::IsHandledFile( const std::string& filename)
68 return (mReader.CanRead(filename));
70 //=====================================================================
72 //=====================================================================
73 void TreeHandlerImageAdder::AddFiles( const std::vector<std::string>& filenames)
77 //unsigned int nbf = filenames.size();
78 std::vector<std::string>::const_iterator i;
79 mSynchronizer->GetList(mCurrentDB);
80 for (i=filenames.begin();i!=filenames.end();++i)
83 mProgress.IncNumberScannedFiles();
84 if (IsHandledFile(*i))
86 mProgress.IncNumberHandledFiles();
87 if(mSynchronizer->isIndexed(*i))
89 mSynchronizer->InsertAddOp((*i),"0","1",mCurrentDB);
90 std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","ADD_OPS","PATH",(*i),mCurrentDB);
91 std::stringstream removedOn;
93 mSynchronizer->InsertIgnoreFile(addKey,(*i),"0",removedOn.str(),mCurrentDB);
97 mProgressSignal(mProgress);
98 if (mProgress.GetStop()) break;
101 //=====================================================================
103 //=====================================================================
104 void TreeHandlerImageAdder::AddDirectory( const std::string& directory,
108 std::stringstream files;
110 std::stringstream rec;
112 mSynchronizer->InsertAddOp(directory,rec.str(),"0",mCurrentDB);
113 std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","ADD_OPS","PATH",directory,mCurrentDB);
114 mTreeHandler->BeginTransaction();
115 mSynchronizer->GetList(mCurrentDB);
116 AddDirectoryRecursor( directory, recurse, addKey );
117 //DicomImageScanner sc;
118 //AddDirectoryRecursorScanner(directory, recurse, addKey, sc, false );
120 int nFiles=GetProgress().GetNumberAddedFiles();
122 mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",files.str(),"ADD_KEY",addKey,mCurrentDB);
123 mTreeHandler->EndTransaction();
124 GimmickDebugMessage(3,mProgress<<std::endl);
127 //=====================================================================
128 void TreeHandlerImageAdder::AddFile( const std::string& filename )
130 GimmickDebugMessage(4,"Adding '"<<filename<<"'"<<std::endl);
131 std::map< std::string, std::string> attr;
132 mTreeHandler->GetTree().GetDescriptor().BuildAttributeMap(attr);
135 mReader.ReadAttributes(filename,attr);
136 //// TO DO Create a function to test if the SOP Instance ID (0008,0018) is not already on DB
137 //// test befor if this attr is present on DB if not don't perform the test!!!
138 //bool bSOPIID = false;
139 //std::map<std::string, std::string>::iterator it_att = attr.begin();
140 //for(; it_att != attr.end(); it_att++)
142 // if (it_att->first == "D0008_0018")
144 // bSOPIID = mTreeHandler->TestSOPIID(it_attr->second);
151 int lev = mTreeHandler->AddBranch(attr);
153 // update the progress according to lev
154 if (lev<mTreeHandler->GetTree().GetNumberOfLevels())
155 mProgress.IncNumberAddedFiles();
157 //=====================================================================
159 void TreeHandlerImageAdder::RemoveFile( tree::Node* node)
161 int n=node->GetNumberOfChildren();
164 RemoveFiles(node->GetChildrenList());
172 //=====================================================================
174 void TreeHandlerImageAdder::RemoveFiles(const std::vector<tree::Node*>& nodes)
176 std::vector<tree::Node*>::const_iterator it;
177 for(it=nodes.begin();it!=nodes.end();++it)
179 int n=(*it)->GetNumberOfChildren();
182 RemoveFiles((*it)->GetChildrenList());
193 void TreeHandlerImageAdder::remove( tree::Node* i_node)
195 std::string path=i_node->GetAttribute("FullFileName");
197 std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","IGNORED_FILES","PATH",path,mCurrentDB);
198 //Gets the number of files added
199 int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",addKey,mCurrentDB)).c_str());
201 std::stringstream out;
203 //Sets the new number of files
204 mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",out.str(),"ADD_KEY",addKey,mCurrentDB);
205 //Sets the file as removed
206 mSynchronizer->SetAttribute("REMOVE","IGNORED_FILES","1","PATH = '"+path+"' AND ADD_KEY",addKey,mCurrentDB);
210 //=======================================================================
211 //=====================================================================
212 #if defined(USE_GDCM2)
214 void TreeHandlerImageAdder::AddDirectoryRecursorScanner(const std::string &dirpath,
215 bool recursive,const std::string &addKey, DicomImageScanner i_sc, bool b_loaded)
217 GimmickDebugMessage(4,"Scanning '"<<dirpath<<"'"<<std::endl);
218 mProgress.IncNumberScannedDirs();
220 if ( !fs::exists( dirpath ) ) return;
221 time_t lastModif=fs::last_write_time(dirpath);
225 std::map< std::string, std::string> attr;
226 mTreeHandler->GetTree().GetDescriptor().BuildAttributeMap(attr);
227 std::string path = dirpath.c_str();
228 i_sc.addDirectory(path, attr);
231 fs::directory_iterator end_itr; // default construction yields past-the-end
232 for ( fs::directory_iterator itr( dirpath );
237 // If is directory & recurse : do recurse
238 if ( fs::is_directory(itr->status()) )
242 AddDirectoryRecursorScanner( itr->path().string(), recursive, addKey, i_sc, true);
247 std::string parent_id;
248 // tTest if directory (and only it) exists or not.
249 bool valid = mSynchronizer->isIndexed(itr->path().string());//true;//=mTimestampHandler->AddDirectory(dirpath, itr->string(), lastModif, time(0),mCurrentDB);
252 std::string path(itr->path().string());
253 mProgress.IncNumberScannedFiles();
254 boost::algorithm::replace_all( path,INVALID_FILE_SEPARATOR,VALID_FILE_SEPARATOR);
255 i_sc.ReadAttributes(itr->path().string(),attr);
256 // mTreeHandler->GetTopLevelNodeId("FullFileName",itr->string(),parent_id);
257 mTreeHandler->AddBranch(attr);
258 mProgress.IncNumberHandledFiles();
259 std::stringstream removedOn;
261 mSynchronizer->InsertIgnoreFile(addKey, path,"0",removedOn.str(),mCurrentDB);
264 mProgressSignal(mProgress);
265 if (mProgress.GetStop())
276 //=====================================================================
277 void TreeHandlerImageAdder::AddDirectoryRecursor(const std::string &dirpath,
279 const std::string &addKey)
281 GimmickDebugMessage(4,"Scanning '"<<dirpath<<"'"<<std::endl);
282 mProgress.IncNumberScannedDirs();
284 if ( !fs::exists( dirpath ) ) return;
286 /// \TODO fix warning: unused variable lastModif
287 time_t lastModif=fs::last_write_time(dirpath);
289 fs::directory_iterator end_itr; // default construction yields past-the-end
290 for ( fs::directory_iterator itr( dirpath );
294 // If is directory & recurse : do recurse
295 if ( fs::is_directory(itr->status()) )
299 AddDirectoryRecursor( itr->path().string(), recursive, addKey);
304 std::string parent_id;
305 // tTest if directory (and only it) exists or not.
306 bool valid = mSynchronizer->isIndexed(itr->path().string());//true;//=mTimestampHandler->AddDirectory(dirpath, itr->string(), lastModif, time(0),mCurrentDB);
309 mProgress.IncNumberScannedFiles();
310 if (IsHandledFile(itr->path().string()))
312 mProgress.IncNumberHandledFiles();
313 AddFile( itr->path().string() );
314 //mTreeHandler->GetTopLevelNodeId("FullFileName",itr->string(),parent_id);
315 std::stringstream removedOn;
317 mSynchronizer->InsertIgnoreFile(addKey, itr->path().string(),"0",removedOn.str(),mCurrentDB);
320 mProgressSignal(mProgress);
321 if (mProgress.GetStop())
332 //=======================================================================
335 //=======================================================================
337 void TreeHandlerImageAdder::CheckSyncDirectory(const std::string &dirpath,
340 bool checkAttributes,
341 std::vector<std::string> &i_ignorefiles,
342 std::vector<std::string> & attsModified,
343 std::vector<std::string> & newfiles)
345 if ( !fs::exists( dirpath ) ) return;
346 fs::directory_iterator end_itr; // default construction yields past-the-end
348 for ( fs::directory_iterator itr( dirpath ); itr != end_itr; ++itr )
350 // If is directory & recurse : do recurse
351 if ( fs::is_directory(itr->status()) )
355 CheckSyncDirectory( itr->path().string(), recursive, repair, checkAttributes, i_ignorefiles, attsModified, newfiles);
360 if (IsHandledFile(itr->path().string()))
363 for(std::vector<std::string>::iterator it_new = i_ignorefiles.begin(); it_new < i_ignorefiles.end(); ++it_new)
365 if((*it_new) == itr->path().string())
368 //Additional checking of attributes
371 CheckAttributes(repair,(*it_new),attsModified);
373 i_ignorefiles.erase(it_new);
377 if(!bfound && i_ignorefiles.size()>0 )
379 newfiles.push_back( itr->path().string() );
386 //=======================================================================
388 //=======================================================================
390 std::string TreeHandlerImageAdder::Synchronize(bool repair, bool checkAttributes)
392 std::vector<AddList> fileList;
393 std::vector<std::string> ignoreList;
394 std::vector<std::string> newFiles;
395 std::vector<std::string> attsModified;
396 std::stringstream mess;
397 std::vector<AddList>::iterator iter;
399 //Gets the list of added files
400 mSynchronizer->GetFileList(fileList,mCurrentDB);
402 std::vector<std::string>::iterator i;
403 //Actions to take if the user doesn't want to repair
406 //Iterates to see if they are in sync
407 for(iter=fileList.begin();iter!=fileList.end();++iter)
409 mSynchronizer->GetIgnoredFiles((*iter).key,ignoreList);
411 if((*iter).recursive=="0"){rec=false;}
412 CheckSyncDirectory((*iter).path,rec,repair,checkAttributes,ignoreList,attsModified,newFiles);
415 //Add to message the result of new found files
416 mess<<"New Files Found: "<<newFiles.size()<<std::endl;
417 if(newFiles.size()>0)
419 mess<<"Filenames: "<<std::endl;
420 for(i=newFiles.begin();i!=newFiles.end();++i)
426 //Add to message the result of missing files
427 mess<<"Missing Files: "<<ignoreList.size()<<std::endl;
428 if(ignoreList.size()>0)
430 mess<<"Filenames: "<<std::endl;
431 for(i=ignoreList.begin();i!=ignoreList.end();++i)
437 //In the case that the user wants to check the attributes...
440 //... add to message the result of files that have been changed.
441 mess<<"Files with different attributes: "<<attsModified.size()<<std::endl;
442 if(attsModified.size()>0)
444 mess<<"Filenames: "<<std::endl;
445 for(i=attsModified.begin();i!=attsModified.end();++i)
454 //Actions to take if the user wants to repair
458 //Iterates to see if they are in sync
459 for(iter=fileList.begin();iter!=fileList.end();++iter)
461 mSynchronizer->GetIgnoredFiles((*iter).key,ignoreList);
463 if((*iter).recursive=="0"){rec=false;}
464 CheckSyncDirectory((*iter).path,rec,repair,checkAttributes,ignoreList,attsModified,newFiles);
466 //For the new files, add them
467 for (i=newFiles.begin();i!=newFiles.end();++i)
469 if (IsHandledFile(*i))
471 std::stringstream removedOn;
473 mSynchronizer->InsertIgnoreFile((*iter).key,(*i),"0",removedOn.str(),mCurrentDB);
474 //Gets the number of files added
475 int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",(*iter).key,mCurrentDB)).c_str());
477 std::stringstream out;
479 //Sets the new number of files
480 mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",out.str(),"ADD_KEY",(*iter).key,mCurrentDB);
484 nf+=(int)newFiles.size();
488 //Reports number of added files
489 mess<<"Files Added: "<<nf<<std::endl;
491 //Removes the necessary files and reports the results
492 if(ignoreList.size()>0)
495 mTreeHandler->LoadChildren(NULL,4);
496 for(i=ignoreList.begin();i!=ignoreList.end();++i)
498 FindNode(mTreeHandler->GetTree().GetChildrenList()[0],3,"FullFileName",*i,node);
500 mTreeHandler->Remove(node);
503 mess<<"Files Removed: "<<ignoreList.size()<<std::endl;
504 //In the case that the user wants to check the attributes...
507 //... add to message the result of files that were modified.
508 mess<<"Files Modified: "<<attsModified.size()<<std::endl;
514 //=======================================================================
516 void TreeHandlerImageAdder::CheckAttributes(bool repair, std::string& file, std::vector<std::string>& attsModified)
518 std::map< std::string, std::string> attr;
519 mTreeHandler->GetTree().GetDescriptor().BuildAttributeMap(attr);
520 mReader.ReadAttributes(file,attr);
521 tree::LevelDescriptor::AttributeDescriptorListType adl= mTreeHandler->GetTree().GetAttributeDescriptorList(mTreeHandler->GetTree().GetNumberOfLevels()-1);
522 tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a;
523 for (a = adl.begin();a!=adl.end();++a)
525 std::string databaseVal;
526 mTreeHandler->GetAttribute("Image","FullFileName",file,a->GetKey(),databaseVal);
527 std::string fileVal=attr.find(a->GetKey())->second;
528 if ( a->GetFlags()==0 && databaseVal == fileVal)
532 mTreeHandler->SetAttribute("Image",a->GetKey(),fileVal,"FullFileName", file);
534 attsModified.push_back(file);
541 //=======================================================================
544 void TreeHandlerImageAdder::FindNode(tree::Node* parent, int level, const std::string& searchParam, const std::string& searchVal, tree::Node*& node)
548 std::vector<tree::Node*>::iterator iter;
549 for(iter=parent->GetChildrenList().begin();iter!=parent->GetChildrenList().end();++iter)
551 FindNode(*iter,level-1,searchParam,searchVal,node);
556 if(parent->GetAttribute(searchParam).compare(searchVal)==0)
564 void TreeHandlerImageAdder::SaveAs(const std::vector<std::string>& filenames, std::vector<vtkImageData *> i_images)
566 std::vector<std::string>::const_iterator it_file = filenames.begin();
567 std::vector<vtkImageData *>::iterator it_image = i_images.begin();
568 /* mWriter.CanWrite(".jpeg");
569 for(; it_file != filenames.end(); ++it_file, ++it_image)
570 mWriter.WriteImage(it_file->c_str(), (vtkImageData &)it_image);*/
573 //=======================================================================
574 void TreeHandlerImageAdder::FindNodePartial(tree::Node* parent, int level, const std::string& searchParam, const std::string& searchVal, tree::Node*& node)
578 std::vector<tree::Node*>::iterator iter;
579 for(iter=parent->GetChildrenList().begin();iter!=parent->GetChildrenList().end() && node==0 ;++iter)
581 FindNodePartial(*iter,level-1,searchParam,searchVal,node);
586 if(parent->GetAttribute(searchParam).find(searchVal)<9000)
595 //=======================================================================
597 void TreeHandlerImageAdder::CopyFiles(const std::vector<std::string>& filenames, const std::string directory )
599 std::vector<std::string>::const_iterator i;
600 if(!boost::filesystem::exists(directory))
602 boost::filesystem::create_directory(boost::filesystem::path(directory));
603 mSynchronizer->InsertAddOp(directory,"0","0",mCurrentDB);
605 std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","ADD_OPS","PATH",directory,mCurrentDB);
607 std::vector<std::string> newNames;
608 for(i=filenames.begin();i!=filenames.end();++i)
610 std::string dir=directory.c_str();
611 if(boost::filesystem::exists(*i) && (*i).find(dir)==std::string::npos)
614 last=(*i).find_last_of('/');
615 std::string f="\\"+(*i).substr(last+1);
618 std::stringstream out;
620 while(boost::filesystem::exists(out.str()))
623 out<<directory<<f.substr(0,f.size()-4)<<"("<<p<<")"<<f.substr(f.size()-4);
626 std::string result=out.str();
627 boost::filesystem::copy_file((*i),result);
629 //To update image database
630 mTreeHandler->SetAttribute("Image","FullFileName",result,"FullFileName", (*i));
632 //To update maintenance database
633 //1.Add the new path and increase number of children on new operation.
634 std::stringstream removedOn;
637 mSynchronizer->InsertIgnoreFile(addKey, result,"0",removedOn.str(),mCurrentDB);
638 //Gets the number of files added
639 int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",addKey,mCurrentDB)).c_str());
641 std::stringstream fil;
643 //Sets the new number of files
644 mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",fil.str(),"ADD_KEY",addKey,mCurrentDB);
647 //2.Set the old path as removed and decrease number of children on old operation.
648 //Gets the old add key
649 std::string oldAddKey=mSynchronizer->GetAttribute("ADD_KEY","IGNORED_FILES","PATH",path,mCurrentDB);
650 //Sets the file as removed
651 mSynchronizer->SetAttribute("REMOVE","IGNORED_FILES","1","PATH = '"+path+"' AND ADD_KEY",oldAddKey,mCurrentDB);
652 //Gets the number of files added
653 files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",oldAddKey,mCurrentDB)).c_str());
656 //Sets the new number of files
657 mSynchronizer->SetAttribute("FILES_ADDED","ADD_OPS",fil.str(),"ADD_KEY",oldAddKey,mCurrentDB);
664 //=======================================================================
666 void TreeHandlerImageAdder::DeleteDriveFromMainDB(const std::string& drive)
668 //Delete from local database and others
670 mTreeHandler->LoadChildren(NULL,4);
671 FindNodePartial(mTreeHandler->GetTree().GetChildrenList()[0],3,"FullFileName",drive,node);
674 mTreeHandler->Remove(node);
676 mTreeHandler->LoadChildren(NULL,4);
677 FindNodePartial(mTreeHandler->GetTree().GetChildrenList()[0],3,"FullFileName",drive,node);
681 //=======================================================================
683 void TreeHandlerImageAdder::DeleteDriveFromOtherDB(const std::string& drive)
685 //Delete from maintenance
686 mSynchronizer->RemoveEntries("ADD_OPS", "PATH", "LIKE", drive+"%");
687 mSynchronizer->RemoveEntries("IGNORED_FILES", "PATH", "LIKE", drive+"%");
690 //=======================================================================
691 void TreeHandlerImageAdder::EditField(tree::Node* node, const std::string& name, const std::string& key, const std::string& val)
693 node->SetAttribute(key,val);
694 mTreeHandler->SetAttribute(node,key,val);
697 //=======================================================================
698 void TreeHandlerImageAdder::GetAttributes(const std::vector<std::string>& params,
699 const std::string& filename,
700 std::vector<std::string>& results)
702 std::vector<std::string>::const_iterator i;
704 for(i=params.begin();i!=params.end();i++)
706 mTreeHandler->GetAttribute("Image","FullFileName",filename,*i,result);
707 results.push_back(result);
711 //=======================================================================
712 const std::string TreeHandlerImageAdder::isAttributeExist(const std::string i_attr)
714 return mTreeHandler->GetTree().isAttributeExist(i_attr);