/* # --------------------------------------------------------------------- # # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image # pour la Santé) # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton # Previous Authors : Laurent Guigues, Jean-Pierre Roux # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil # # This software is governed by the CeCILL-B license under French law and # abiding by the rules of distribution of free software. You can use, # modify and/ or redistribute the software under the terms of the CeCILL-B # license as circulated by CEA, CNRS and INRIA at the following URL # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html # or in the file LICENSE.txt. # # As a counterpart to the access to the source code and rights to copy, # modify and redistribute granted by the license, users are provided only # with a limited warranty and the software's author, the holder of the # economic rights, and the successive licensors have only limited # liability. # # The fact that you are presently reading this means that you have had # knowledge of the CeCILL-B license and that you accept its terms. # ------------------------------------------------------------------------ */ #include #include #include #include #include namespace fs = boost::filesystem; using boost::filesystem::path; using boost::next; using boost::prior; using namespace crea; using namespace boost; namespace creaImageIO { //==================================================================== // Ctor TreeHandlerImageAdder::TreeHandlerImageAdder(TreeHandler* tree) : mTreeHandler(tree) { } // Dtor TreeHandlerImageAdder::~TreeHandlerImageAdder() { } //==================================================================== //==================================================================== void TreeHandlerImageAdder::ConnectProgressObserver(ProgressCallbackType callback) { mProgressSignal.connect(callback); } //==================================================================== //===================================================================== bool TreeHandlerImageAdder::IsHandledFile( const std::string& filename) { return (mReader.CanRead(filename)); } //===================================================================== //===================================================================== void TreeHandlerImageAdder::AddFiles( const std::vector& filenames) { mProgress.Reset(); //unsigned int nbf = filenames.size(); std::vector::const_iterator i; mSynchronizer->GetList(mCurrentDB); for (i=filenames.begin();i!=filenames.end();++i) { mProgress.IncNumberScannedFiles(); if (IsHandledFile(*i)) { mProgress.IncNumberHandledFiles(); if(mSynchronizer->isIndexed(*i)) { mSynchronizer->InsertAddOp((*i),"0","1",mCurrentDB); std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","ADD_OPS","PATH",(*i),mCurrentDB); std::stringstream removedOn; removedOn<InsertIgnoreFile(addKey,(*i),"0",removedOn.str(),mCurrentDB); AddFile(*i); } } mProgressSignal(mProgress); if (mProgress.GetStop()) break; } } //===================================================================== //===================================================================== void TreeHandlerImageAdder::AddDirectory( const std::string& directory, bool recurse) { mProgress.Reset(); std::stringstream files; std::stringstream rec; rec<InsertAddOp(directory,rec.str(),"0",mCurrentDB); std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","ADD_OPS","PATH",directory,mCurrentDB); mTreeHandler->BeginTransaction(); mSynchronizer->GetList(mCurrentDB); AddDirectoryRecursor( directory, recurse, addKey ); //DicomImageScanner sc; //AddDirectoryRecursorScanner(directory, recurse, addKey, sc, false ); int nFiles=GetProgress().GetNumberAddedFiles(); files<SetAttribute("FILES_ADDED","ADD_OPS",files.str(),"ADD_KEY",addKey,mCurrentDB); mTreeHandler->EndTransaction(); GimmickDebugMessage(3,mProgress< attr; mTreeHandler->GetTree().GetDescriptor().BuildAttributeMap(attr); mReader.ReadAttributes(filename,attr); //// TO DO Create a function to test if the SOP Instance ID (0008,0018) is not already on DB //// test befor if this attr is present on DB if not don't perform the test!!! //bool bSOPIID = false; //std::map::iterator it_att = attr.begin(); //for(; it_att != attr.end(); it_att++) //{ // if (it_att->first == "D0008_0018") // { // bSOPIID = mTreeHandler->TestSOPIID(it_attr->second); // break; // } //} //if(bSOPIID) // return; int lev = mTreeHandler->AddBranch(attr); // update the progress according to lev if (levGetTree().GetNumberOfLevels()) mProgress.IncNumberAddedFiles(); } //===================================================================== void TreeHandlerImageAdder::RemoveFile( tree::Node* node) { int n=node->GetNumberOfChildren(); if(n>0) { RemoveFiles(node->GetChildrenList()); } else { remove(node); } } //===================================================================== void TreeHandlerImageAdder::RemoveFiles(const std::vector& nodes) { std::vector::const_iterator it; for(it=nodes.begin();it!=nodes.end();++it) { int n=(*it)->GetNumberOfChildren(); if(n>0) { RemoveFiles((*it)->GetChildrenList()); } else { remove(*it); } } } void TreeHandlerImageAdder::remove( tree::Node* i_node) { std::string path=i_node->GetAttribute("FullFileName"); //Gets the add key std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","IGNORED_FILES","PATH",path,mCurrentDB); //Gets the number of files added int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",addKey,mCurrentDB)).c_str()); files=files-1; std::stringstream out; out<SetAttribute("FILES_ADDED","ADD_OPS",out.str(),"ADD_KEY",addKey,mCurrentDB); //Sets the file as removed mSynchronizer->SetAttribute("REMOVE","IGNORED_FILES","1","PATH = '"+path+"' AND ADD_KEY",addKey,mCurrentDB); } //======================================================================= //===================================================================== #if defined(USE_GDCM2) void TreeHandlerImageAdder::AddDirectoryRecursorScanner(const std::string &dirpath, bool recursive,const std::string &addKey, DicomImageScanner i_sc, bool b_loaded) { GimmickDebugMessage(4,"Scanning '"< attr; mTreeHandler->GetTree().GetDescriptor().BuildAttributeMap(attr); std::string path = dirpath.c_str(); i_sc.addDirectory(path, attr); fs::directory_iterator end_itr; // default construction yields past-the-end for ( fs::directory_iterator itr( dirpath ); itr != end_itr; ++itr ) { // If is directory & recurse : do recurse if ( fs::is_directory(itr->status()) ) { if (recursive) { AddDirectoryRecursorScanner( itr->path().string(), recursive, addKey, i_sc, true); } } else { std::string parent_id; // tTest if directory (and only it) exists or not. bool valid = mSynchronizer->isIndexed(itr->path().string());//true;//=mTimestampHandler->AddDirectory(dirpath, itr->string(), lastModif, time(0),mCurrentDB); if(valid) { std::string path(itr->path().string()); mProgress.IncNumberScannedFiles(); boost::algorithm::replace_all( path,INVALID_FILE_SEPARATOR,VALID_FILE_SEPARATOR); i_sc.ReadAttributes(itr->path().string(),attr); // mTreeHandler->GetTopLevelNodeId("FullFileName",itr->string(),parent_id); mTreeHandler->AddBranch(attr); mProgress.IncNumberHandledFiles(); std::stringstream removedOn; removedOn<InsertIgnoreFile(addKey, path,"0",removedOn.str(),mCurrentDB); mProgressSignal(mProgress); if (mProgress.GetStop()) { //itr = end_itr; break; } } } } } #endif //===================================================================== void TreeHandlerImageAdder::AddDirectoryRecursor(const std::string &dirpath, bool recursive, const std::string &addKey) { GimmickDebugMessage(4,"Scanning '"<status()) ) { if (recursive) { AddDirectoryRecursor( itr->path().string(), recursive, addKey); } } else { std::string parent_id; // tTest if directory (and only it) exists or not. bool valid = mSynchronizer->isIndexed(itr->path().string());//true;//=mTimestampHandler->AddDirectory(dirpath, itr->string(), lastModif, time(0),mCurrentDB); if(valid) { mProgress.IncNumberScannedFiles(); if (IsHandledFile(itr->path().string())) { mProgress.IncNumberHandledFiles(); AddFile( itr->path().string() ); //mTreeHandler->GetTopLevelNodeId("FullFileName",itr->string(),parent_id); std::stringstream removedOn; removedOn<InsertIgnoreFile(addKey, itr->path().string(),"0",removedOn.str(),mCurrentDB); } mProgressSignal(mProgress); if (mProgress.GetStop()) { //itr = end_itr; break; } } } } } //======================================================================= //======================================================================= void TreeHandlerImageAdder::CheckSyncDirectory(const std::string &dirpath, bool recursive, bool repair, bool checkAttributes, std::vector &i_ignorefiles, std::vector & attsModified, std::vector & newfiles) { if ( !fs::exists( dirpath ) ) return; fs::directory_iterator end_itr; // default construction yields past-the-end for ( fs::directory_iterator itr( dirpath ); itr != end_itr; ++itr ) { // If is directory & recurse : do recurse if ( fs::is_directory(itr->status()) ) { if (recursive) { CheckSyncDirectory( itr->path().string(), recursive, repair, checkAttributes, i_ignorefiles, attsModified, newfiles); } } else { if (IsHandledFile(itr->path().string())) { bool bfound = false; for(std::vector::iterator it_new = i_ignorefiles.begin(); it_new < i_ignorefiles.end(); ++it_new) { if((*it_new) == itr->path().string()) { bfound = true; //Additional checking of attributes if(checkAttributes) { CheckAttributes(repair,(*it_new),attsModified); } i_ignorefiles.erase(it_new); break; } } if(!bfound && i_ignorefiles.size()>0 ) { newfiles.push_back( itr->path().string() ); } } } } } //======================================================================= //======================================================================= std::string TreeHandlerImageAdder::Synchronize(bool repair, bool checkAttributes) { std::vector fileList; std::vector ignoreList; std::vector newFiles; std::vector attsModified; std::stringstream mess; std::vector::iterator iter; //Gets the list of added files mSynchronizer->GetFileList(fileList,mCurrentDB); std::vector::iterator i; //Actions to take if the user doesn't want to repair if(!repair) { //Iterates to see if they are in sync for(iter=fileList.begin();iter!=fileList.end();++iter) { mSynchronizer->GetIgnoredFiles((*iter).key,ignoreList); bool rec=true; if((*iter).recursive=="0"){rec=false;} CheckSyncDirectory((*iter).path,rec,repair,checkAttributes,ignoreList,attsModified,newFiles); } //Add to message the result of new found files mess<<"New Files Found: "<0) { mess<<"Filenames: "<0) { mess<<"Filenames: "<0) { mess<<"Filenames: "<GetIgnoredFiles((*iter).key,ignoreList); bool rec=true; if((*iter).recursive=="0"){rec=false;} CheckSyncDirectory((*iter).path,rec,repair,checkAttributes,ignoreList,attsModified,newFiles); //For the new files, add them for (i=newFiles.begin();i!=newFiles.end();++i) { if (IsHandledFile(*i)) { std::stringstream removedOn; removedOn<InsertIgnoreFile((*iter).key,(*i),"0",removedOn.str(),mCurrentDB); //Gets the number of files added int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",(*iter).key,mCurrentDB)).c_str()); files=files+1; std::stringstream out; out<SetAttribute("FILES_ADDED","ADD_OPS",out.str(),"ADD_KEY",(*iter).key,mCurrentDB); AddFile(*i); } } nf+=(int)newFiles.size(); newFiles.clear(); } //Reports number of added files mess<<"Files Added: "<0) { tree::Node* node; mTreeHandler->LoadChildren(NULL,4); for(i=ignoreList.begin();i!=ignoreList.end();++i) { FindNode(mTreeHandler->GetTree().GetChildrenList()[0],3,"FullFileName",*i,node); RemoveFile(node); mTreeHandler->Remove(node); } } mess<<"Files Removed: "<& attsModified) { std::map< std::string, std::string> attr; mTreeHandler->GetTree().GetDescriptor().BuildAttributeMap(attr); mReader.ReadAttributes(file,attr); tree::LevelDescriptor::AttributeDescriptorListType adl= mTreeHandler->GetTree().GetAttributeDescriptorList(mTreeHandler->GetTree().GetNumberOfLevels()-1); tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a; for (a = adl.begin();a!=adl.end();++a) { std::string databaseVal; mTreeHandler->GetAttribute("Image","FullFileName",file,a->GetKey(),databaseVal); std::string fileVal=attr.find(a->GetKey())->second; if ( a->GetFlags()==0 && databaseVal == fileVal) { if(repair) { mTreeHandler->SetAttribute("Image",a->GetKey(),fileVal,"FullFileName", file); } attsModified.push_back(file); } } } //======================================================================= void TreeHandlerImageAdder::FindNode(tree::Node* parent, int level, const std::string& searchParam, const std::string& searchVal, tree::Node*& node) { if(level>1) { std::vector::iterator iter; for(iter=parent->GetChildrenList().begin();iter!=parent->GetChildrenList().end();++iter) { FindNode(*iter,level-1,searchParam,searchVal,node); } } else { if(parent->GetAttribute(searchParam).compare(searchVal)==0) { node=parent; } } } void TreeHandlerImageAdder::SaveAs(const std::vector& filenames, std::vector i_images) { std::vector::const_iterator it_file = filenames.begin(); std::vector::iterator it_image = i_images.begin(); /* mWriter.CanWrite(".jpeg"); for(; it_file != filenames.end(); ++it_file, ++it_image) mWriter.WriteImage(it_file->c_str(), (vtkImageData &)it_image);*/ } //======================================================================= void TreeHandlerImageAdder::FindNodePartial(tree::Node* parent, int level, const std::string& searchParam, const std::string& searchVal, tree::Node*& node) { if(level>1) { std::vector::iterator iter; for(iter=parent->GetChildrenList().begin();iter!=parent->GetChildrenList().end() && node==0 ;++iter) { FindNodePartial(*iter,level-1,searchParam,searchVal,node); } } else { if(parent->GetAttribute(searchParam).find(searchVal)<9000) { node=parent; return; } } } //======================================================================= void TreeHandlerImageAdder::CopyFiles(const std::vector& filenames, const std::string directory ) { std::vector::const_iterator i; if(!boost::filesystem::exists(directory)) { boost::filesystem::create_directory(boost::filesystem::path(directory)); mSynchronizer->InsertAddOp(directory,"0","0",mCurrentDB); } std::string addKey=mSynchronizer->GetAttribute("ADD_KEY","ADD_OPS","PATH",directory,mCurrentDB); size_t last; std::vector newNames; for(i=filenames.begin();i!=filenames.end();++i) { std::string dir=directory.c_str(); if(boost::filesystem::exists(*i) && (*i).find(dir)==std::string::npos) { std::string path=*i; last=(*i).find_last_of('/'); std::string f="\\"+(*i).substr(last+1); int p=1; std::stringstream out; out<SetAttribute("Image","FullFileName",result,"FullFileName", (*i)); //To update maintenance database //1.Add the new path and increase number of children on new operation. std::stringstream removedOn; removedOn<InsertIgnoreFile(addKey, result,"0",removedOn.str(),mCurrentDB); //Gets the number of files added int files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",addKey,mCurrentDB)).c_str()); files=files+1; std::stringstream fil; fil<SetAttribute("FILES_ADDED","ADD_OPS",fil.str(),"ADD_KEY",addKey,mCurrentDB); fil.str(""); //2.Set the old path as removed and decrease number of children on old operation. //Gets the old add key std::string oldAddKey=mSynchronizer->GetAttribute("ADD_KEY","IGNORED_FILES","PATH",path,mCurrentDB); //Sets the file as removed mSynchronizer->SetAttribute("REMOVE","IGNORED_FILES","1","PATH = '"+path+"' AND ADD_KEY",oldAddKey,mCurrentDB); //Gets the number of files added files=atoi((mSynchronizer->GetAttribute("FILES_ADDED","ADD_OPS","ADD_KEY",oldAddKey,mCurrentDB)).c_str()); files=files-1; fil<SetAttribute("FILES_ADDED","ADD_OPS",fil.str(),"ADD_KEY",oldAddKey,mCurrentDB); } } } //======================================================================= void TreeHandlerImageAdder::DeleteDriveFromMainDB(const std::string& drive) { //Delete from local database and others tree::Node* node=0; mTreeHandler->LoadChildren(NULL,4); FindNodePartial(mTreeHandler->GetTree().GetChildrenList()[0],3,"FullFileName",drive,node); while(node!=0) { mTreeHandler->Remove(node); node=0; mTreeHandler->LoadChildren(NULL,4); FindNodePartial(mTreeHandler->GetTree().GetChildrenList()[0],3,"FullFileName",drive,node); } } //======================================================================= void TreeHandlerImageAdder::DeleteDriveFromOtherDB(const std::string& drive) { //Delete from maintenance mSynchronizer->RemoveEntries("ADD_OPS", "PATH", "LIKE", drive+"%"); mSynchronizer->RemoveEntries("IGNORED_FILES", "PATH", "LIKE", drive+"%"); } //======================================================================= void TreeHandlerImageAdder::EditField(tree::Node* node, const std::string& name, const std::string& key, const std::string& val) { node->SetAttribute(key,val); mTreeHandler->SetAttribute(node,key,val); } //======================================================================= void TreeHandlerImageAdder::GetAttributes(const std::vector& params, const std::string& filename, std::vector& results) { std::vector::const_iterator i; std::string result; for(i=params.begin();i!=params.end();i++) { mTreeHandler->GetAttribute("Image","FullFileName",filename,*i,result); results.push_back(result); } } //======================================================================= const std::string TreeHandlerImageAdder::isAttributeExist(const std::string i_attr) { return mTreeHandler->GetTree().isAttributeExist(i_attr); } }