X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=kernel%2Fappli%2FbbpConfigurator%2FbbpConfigurator.cpp;fp=kernel%2Fappli%2FbbpConfigurator%2FbbpConfigurator.cpp;h=a4fa7ac72ba0b355723e2bb8eba208078f6bb07b;hb=427d8c0ac838ab789a57b28f62a7f9ff243e7b60;hp=0000000000000000000000000000000000000000;hpb=c2d2ccbc4bac635e5d0b802d9830efd94b060dab;p=bbtk.git diff --git a/kernel/appli/bbpConfigurator/bbpConfigurator.cpp b/kernel/appli/bbpConfigurator/bbpConfigurator.cpp new file mode 100644 index 0000000..a4fa7ac --- /dev/null +++ b/kernel/appli/bbpConfigurator/bbpConfigurator.cpp @@ -0,0 +1,393 @@ +/* + # --------------------------------------------------------------------- + # + # 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 +#include +#include +#include "boost/filesystem.hpp" +#include "bbtkBBPInterpreter.h" + +namespace bf = boost::filesystem; + +typedef std::vector > Graph; + +typedef std::set Dependencies; +typedef std::vector DependenciesVector; +typedef std::vector BoxesVector; + +std::vector getFileList(const std::string& path); + +bool isCycle(const Graph& g); +bool checkCycle(const Graph& g, const int& i, std::vector& v); + +void setPriorities(const Graph& g, std::vector& p); +void setPriority(const Graph& g, const int i, std::vector& p); + +int main(int argc, char **argv) +{ + // Check arguments + if (argc != 4) + { + std::cout << "bbpConfigurator usage: bbConfigurator " << std::endl; + return 1; + } + + std::string path_bbs(argv[1]); + std::string package_name(argv[2]); + std::string path_out(argv[3]); + + std::cout << "bbpConfigurator launched with bbs path: '" << path_bbs << + "', package: '" << package_name << + "', output path: '" << path_out << "'." << std::endl; + + // Get bbs files in path_bbs + std::vector files = getFileList(path_bbs); + if(files.size() == 0) + { + std::cout << "bbpConfigurator: No files to check in bbs path. " + "An empty bbp will be created for the package '" << package_name << "'." << std::endl; + + // Write results to bbp file + #ifdef WIN32 + std::string fname = path_out + "\\" + package_name + ".bbp"; + #else + std::string fname = path_out + "/" + package_name + ".bbp"; + #endif + + std::ofstream out(fname.c_str()); + out << "#-----------------------------------------" << std::endl; + out << "# Include script for bbtk package '" << package_name << "'" << std::endl; + out << "# Automatically generated by bbpConfigurator" << std::endl; + out << "#-----------------------------------------" << std::endl; + out << "load "<< package_name << std::endl; + out << "#-----------------------------------------" << std::endl; + out << "package "<< package_name << std::endl; + out << "#-----------------------------------------" << std::endl; + out << "endpackage" << std::endl; + out << "#-- EOF ----------------------------------" << std::endl; + + out.close(); + + + return 0; + } + + + // Order files by dependencies + // Get DependenciesVector and Box Names + DependenciesVector deps; + BoxesVector boxs; + + + for (int i = 0; i < (int)files.size(); ++i) + { + bbtk::BBPInterpreter::Pointer I = bbtk::BBPInterpreter::New(); + I->InterpretFile(files[i].string()); + + + boxs.push_back( ((bbtk::BBPInterpreter*)(I.get()))->boxName ); + +// EED 2016/02/19 +// deps.push_back( ((bbtk::BBPInterpreter*)(I.get()))->dependencies ); + //--> Cleanning string package:boxname -> boxname + std::set tmpDependencies1= ((bbtk::BBPInterpreter*)(I.get()))->dependencies ; + std::set tmpDependencies2; + std::set::const_iterator sit(tmpDependencies1.begin()), send(tmpDependencies1.end()); + int pos; + std::string tmpStr; +// std::cout << ((bbtk::BBPInterpreter*)(I.get()))->boxName << ": "; + for(;sit!=send;++sit) + { + pos=(*sit).find(":"); + if (pos== std::string::npos ) + { + tmpDependencies2.insert( *sit ); +// std::cout << *sit << ' '; + } else { + tmpStr=(*sit).substr(pos+1); + tmpDependencies2.insert( tmpStr ); +// std::cout << tmpStr << ' '; + } // if + + } // for +// std::cout << std::endl; + deps.push_back( tmpDependencies2 ); + //<-- + + + +// //print box name and dependencies OLD VERSION +// std::cout << ((bbtk::BBPInterpreter*)(I.get()))->boxName << ": "; +// for( +// Dependencies::iterator it = ((bbtk::BBPInterpreter*)(I.get()))->dependencies.begin(); +// it != ((bbtk::BBPInterpreter*)(I.get()))->dependencies.end(); +// it++) { +// std::cout << *it << ", "; +// } +// std::cout << std::endl; + + } // for i + + // Only keep dependencies from package + Dependencies boxNamesSet(boxs.begin(), boxs.end()); + +//std::cout << "after: " << std::endl; + for (DependenciesVector::iterator it = deps.begin(); it != deps.end(); it++) + { + BoxesVector tmp; + std::set_intersection(it->begin(), it->end(), boxNamesSet.begin(), boxNamesSet.end(),std::back_inserter(tmp)); + Dependencies tmp1(tmp.begin(),tmp.end()); + it->swap( tmp1 ); +// //print clean dependencies +// for( Dependencies::iterator it1 = it->begin(); it1 != it->end(); it1++) +// { +// std::cout << *it1 << ", "; +// } +// std::cout << std::endl; + + } + + // Create dependencies graph + std::vector > g(boxs.size(), std::vector()); + std::map idxs; + + + for (int i = 0; i < (int)boxs.size(); ++i) + { + idxs[boxs[i]] = i; + } + + int boxit = 0; + for (DependenciesVector::iterator dit = deps.begin(); dit != deps.end(); dit++, boxit++) + { + for (Dependencies::iterator ddit = dit->begin(); ddit != dit->end(); ddit++) + { + g[boxit].push_back(idxs[*ddit]); + } + } + + // Check there are no cycles in graph + if(isCycle(g)) + { + std::cout << "bbpConfigurator: There are dependency cycles, please check your scripts in '" << + path_bbs << "'. No bbp file created." << std::endl; + return 2; + } + else + { + std::cout << "bbpConfigurator: No cycles detected in dependency graph." << std::endl; + std::vector priorities(boxs.size(), -1); + setPriorities(g, priorities); +// for (int i = 0; i < (int)priorities.size(); i++) +// { +// std::cout << priorities[i] << " "; +// } +// std::cout << std::endl; + + // Write results to bbp file + #ifdef WIN32 + std::string fname = path_out + "\\" + package_name + ".bbp"; + #else + std::string fname = path_out + "/" + package_name + ".bbp"; + #endif + + std::ofstream out(fname.c_str()); + out << "#-----------------------------------------" << std::endl; + out << "# Include script for bbtk package '" << package_name << "'" << std::endl; + out << "# Automatically generated by bbpConfigurator" << std::endl; + out << "#-----------------------------------------" << std::endl; + out << "load "<< package_name << std::endl; + out << "#-----------------------------------------" << std::endl; + out << "package "<< package_name << std::endl; + out << "#-----------------------------------------" << std::endl; + + //each bbs file ordered. + //include [package_name]/boxes/[file_bbs] + //#----------------------------------------- + + // for (int i = 0; i < (int)files.size(); ++i) { + // out << "include " << package_name << "/boxes/" << files[i].filename().string() << std::endl; + // out << "#-----------------------------------------" << std::endl; + // } + + // find max priority level + int mx_priority = 0; + for (int i = 0; i < (int)priorities.size(); i++) + { + mx_priority = std::max(mx_priority, priorities[i]); + } + + // for each priority level print scripts in that level. + for (int i = 0; i <= mx_priority; i++) + { + for (int j = 0; j < (int)priorities.size(); j++) + { + if(priorities[j] == i) + { +//EED 2017-03-28 +#if BOOST_MAJOR_VERSION <= 1 && BOOST_MINOR_VERSION <=41 + out << "include " << package_name << "/boxes/" << files[j].filename() << std::endl; +#else + out << "include " << package_name << "/boxes/" << files[j].filename().string() << std::endl; +#endif + + out << "#-----------------------------------------" << std::endl; + } + } + } + out << "endpackage" << std::endl; + out << "#-- EOF ----------------------------------" << std::endl; + + out.close(); + + std::cout << "bbpConfigurator: bbp file created at '" << fname << "'." << std::endl; + } + return 0; +} +//========================================================================== + +// extract of the tarjan's algorithm for strongly connected components +bool isCycle(const Graph& g) +{ + for (int it = 0; it < (int)g.size(); ++it) { + std::vector visited (g.size(), false); + if (checkCycle(g, it, visited)) + { + //std::cout << "At " << it << std::endl; + return true; + } + } + return false; +} + +//========================================================================== + +// dfs search to check cycles. +bool checkCycle(const Graph& g, const int& i, std::vector& v) +{ + + v[i] = true; + for(int dit = 0; dit < (int)g[i].size(); dit++) + { + int d = g[i][dit]; + if(d < 0 || d >= (int)g.size() || v[d]) + { + //std::cout << "Checking " << i << " dependency " << dit << "=" << d << std::endl; + return true; + } + if(checkCycle(g,d,v)) + return true; + } + v[i] = false; + return false; +} + +//========================================================================== + +// find precedence in graph. 0 are the boxes that have no deps, 1 boxes that have deps from 0 or less, 2 boxes that have deps from 1 or less, etc. +void setPriorities(const Graph& g, std::vector& p) +{ + for(int i = 0; i < (int)g.size(); i++) + { + if(p[i] == -1) + setPriority(g, i, p); + } +} + +//========================================================================== + +// dfs search to find dependencies +void setPriority(const Graph& g, const int i, std::vector& p) +{ + int pi = -1; + for(int j = 0; j < (int)g[i].size(); j++) + { + setPriority(g, g[i][j], p); + pi = std::max(pi, p[g[i][j]]); + } + p[i]=pi+1; +} + +//========================================================================== + +std::vector getFileList(const std::string& path) +{ + std::vector files; + + bf::path pth(path.c_str()); + if(bf::exists(pth) && bf::is_directory(pth)) + { + bf::directory_iterator end_itr; + bf::directory_iterator itr(pth); + for(itr; itr != end_itr; ++itr) + { + if(!is_directory(itr->status())) + { +//EED 2017-03-28 +#if BOOST_MAJOR_VERSION <= 1 && BOOST_MINOR_VERSION <=41 + std::string nm(itr->path().filename()); +#else + std::string nm(itr->path().filename().string()); +#endif + if(nm.substr(nm.size()-4) == ".bbs") + { + //std::cout << itr->path().filename().string() << std::endl; + files.push_back(itr->path()); + } + } + } + } + else + { + std::cout<< "bbpConfigurator: The path to the bbs's doesn't exist or is not a folder. ('" << path << "')" << std::endl; + return files; + } + + // Order files by name + for (int i = 0; i < (int)files.size()-1; ++i) { + for (int j = i+1; j < (int)files.size(); ++j) { + +//EED 2017-03-28 +#if BOOST_MAJOR_VERSION <= 1 && BOOST_MINOR_VERSION <=41 + if(files[j].filename() < files[i].filename()) +#else + if(files[j].filename().string() < files[i].filename().string()) +#endif + + { + bf::path tmp = files[i]; + files[i] = files[j]; + files[j] = tmp; + } + } + } + + return files; +}