#include <fstream>
#include <iostream>
#include <vector>
+#include <set>
+#include <map>
+#include <algorithm>
#include "boost/filesystem.hpp"
//#include "boost/filesystem/operations.hpp"
//#include "boost/filesystem/path.hpp"
+#include "bbtkBBPInterpreter.h"
namespace bf = boost::filesystem;
+typedef std::vector<std::vector<int> > Graph;
-//using namespace bbtk;
+typedef std::set<std::string> Dependency;
+typedef std::vector<Dependency> Dependencies;
+typedef std::vector<std::string> Boxes;
+
+bool isCycle(const Graph& g);
+bool checkCycle(const Graph& g, const int& i, std::vector<bool>& v);
+
+void setPriorities(const Graph& g, std::vector<int>& p);
+void setPriority(const Graph& g, const int i, std::vector<int>& p);
int main(int argc, char **argv)
{
+ // Check arguments
if (argc != 4)
{
std::cout << "usage : bbConfigurator <path_to_bbs> <package_name> <output_path>" << std::endl;
std::string package_name(argv[2]);
std::string path_out(argv[3]);
+ // Get bbs files in path_bbs
std::vector<bf::path> files;
bf::path pth(path_bbs.c_str());
std::string nm(itr->path().filename().string());
if(nm.substr(nm.size()-4) == ".bbs")
{
- std::cout << itr->path().filename().string() << std::endl;
+ //std::cout << itr->path().filename().string() << std::endl;
files.push_back(itr->path());
}
}
return 1;
}
+ // Order files by name
for (int i = 0; i < (int)files.size()-1; ++i) {
for (int j = i+1; j < (int)files.size(); ++j) {
if(files[j].filename().string() < files[i].filename().string())
}
}
-#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]
- //#-----------------------------------------
+ // Order files by dependencies
+ // Get Dependencies and Box Names
+ Dependencies ds;
+ Boxes bs;
+
+
for (int i = 0; i < (int)files.size(); ++i) {
- out << "include " << package_name << "/boxes/" << files[i].filename().string() << std::endl;
- out << "#-----------------------------------------" << std::endl;
+ bbtk::BBPInterpreter::Pointer I = bbtk::BBPInterpreter::New();
+ I->InterpretFile(files[i].string());
+ bs.push_back( ((bbtk::BBPInterpreter*)(I.get()))->boxName );
+ ds.push_back( ((bbtk::BBPInterpreter*)(I.get()))->dependencies );
+
+ //print box name and dependencies
+/* std::cout << ((bbtk::BBPInterpreter*)(I.get()))->boxName << ": ";
+ for(
+ dep::iterator it = ((bbtk::BBPInterpreter*)(I.get()))->dependencies.begin();
+ it != ((bbtk::BBPInterpreter*)(I.get()))->dependencies.end();
+ it++) {
+ std::cout << *it << ", ";
+ }
+ std::cout << std::endl;
+*/
+ }
+ // Only keep dependencies from package
+ Dependency boxesNamesSet(bs.begin(), bs.end());
+
+ //std::cout << "after: " << std::endl;
+ for (Dependencies::iterator it = ds.begin(); it != ds.end(); it++) {
+ Boxes tmp;
+ std::set_intersection(it->begin(), it->end(), boxesNamesSet.begin(), boxesNamesSet.end(),std::back_inserter(tmp));
+ Dependency tmp1(tmp.begin(),tmp.end());
+ it->swap( tmp1 );
+ //print clean dependencies
+/* for(
+ dep::iterator it1 = it->begin();
+ it1 != it->end();
+ it1++) {
+ std::cout << *it1 << ", ";
+ }
+ std::cout << std::endl;
+*/
+ }
+
+ // Check there are no cycles in graph
+ std::vector<std::vector<int> > g(bs.size(), std::vector<int>());
+ std::map<std::string, int> idxs;
+
+
+ for (int i = 0; i < (int)bs.size(); ++i)
+ {
+ idxs[bs[i]] = i;
+ }
+
+ int boxit = 0;
+ for (Dependencies::iterator dit = ds.begin(); dit != ds.end(); dit++, boxit++)
+ {
+ for (Dependency::iterator ddit = dit->begin(); ddit != dit->end(); ddit++)
+ {
+ g[boxit].push_back(idxs[*ddit]);
+ }
}
- out << "endpackage" << std::endl;
- out << "#-- EOF ----------------------------------" << std::endl;
+ if(isCycle(g))
+ {
+ std::cout << "there are dependency cycles, please check your scripts." << std::endl;
+ return 2;
+ }
+ else
+ {
+ std::cout << "no cycles, we keep going." << std::endl;
+ std::vector<int> dep_priority(bs.size(), -1);
+ setPriorities(g, dep_priority);
+// for (int i = 0; i < (int)dep_priority.size(); i++)
+// {
+// std::cout << dep_priority[i] << " ";
+// }
+// std::cout << std::endl;
- out.close();
+ // 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;
+ // }
+
+ // for each priority level print scripts in that level.
+ int m_priority = 0;
+ for (int i = 0; i < (int)dep_priority.size(); i++)
+ m_priority = std::max(m_priority, dep_priority[i]);
+
+ for (int i = 0; i <= m_priority; i++)
+ {
+ for (int j = 0; j < (int)dep_priority.size(); j++)
+ {
+ if(dep_priority[j] == i)
+ {
+ out << "include " << package_name << "/boxes/" << files[j].filename().string() << std::endl;
+ out << "#-----------------------------------------" << std::endl;
+ }
+ }
+ }
+ out << "endpackage" << std::endl;
+ out << "#-- EOF ----------------------------------" << std::endl;
+
+ out.close();
+ }
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<bool> visited (g.size(), false);
+ if (checkCycle(g, it, visited))
+ {
+ //std::cout << "At " << it << std::endl;
+ return true;
+ }
+ }
+ return false;
+}
+
+//==========================================================================
+
+bool checkCycle(const Graph& g, const int& i, std::vector<bool>& 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[i].size() || v[d])
+ {
+ //std::cout << "Checking " << i << " dependency " << dit << "=" << d << std::endl;
+ return true;
+ }
+ if(checkCycle(g,d,v))
+ return true;
+ }
+ 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<int>& p)
+{
+ for(int i = 0; i < (int)g.size(); i++)
+ {
+ if(p[i] == -1)
+ setPriority(g, i, p);
+ }
+}
+//==========================================================================
+void setPriority(const Graph& g, const int i, std::vector<int>& 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;
+}
--- /dev/null
+/*
+# ---------------------------------------------------------------------
+#
+# Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
+# pour la Santé)
+# Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
+#
+# 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.
+# ------------------------------------------------------------------------
+ */
+
+/*=========================================================================
+Program: bbtk
+Module: $RCSfile$
+Language: C++
+Date: $Date$
+Version: $Revision$
+=========================================================================*/
+
+
+/**
+ * \file
+ * \brief Class bbtk::BBPInterpreter
+ */
+
+
+#include "bbtkBBPInterpreter.h"
+
+#include "bbtkExecuter.h"
+#include "bbtkMessageManager.h"
+#include "bbtkFactory.h"
+#include "bbtkUtilities.h"
+
+namespace bbtk
+{
+
+ //=========================================================================
+ BBPInterpreter::Pointer BBPInterpreter::New()
+ {
+ return MakePointer( new BBPInterpreter() );
+ }
+ //=========================================================================
+
+
+
+ //=========================================================================
+ BBPInterpreter::BBPInterpreter()
+ {
+ bbtk::InterpreterVirtual::Init();
+ }
+ //=========================================================================
+
+
+ //=========================================================================
+ BBPInterpreter::~BBPInterpreter()
+ {
+ }
+ //=========================================================================
+
+
+ //=========================================================================
+ /// Creates a new black box in current complex box
+ void BBPInterpreter::commandNew( const std::string& boxType, const std::string& boxName) // virtual
+ {
+ this->dependencies.insert(boxType);
+ }
+ //=========================================================================
+
+
+ //=========================================================================
+ /// Connects the output boxOutput to the input boxInput
+ void BBPInterpreter::commandConnection (const std::string &boxfrom,
+ const std::string &output,
+ const std::string &boxto,
+ const std::string &input) // virtual
+ {
+ }
+ //=========================================================================
+
+ //=========================================================================
+ void BBPInterpreter::commandInput(const std::string &name,const std::string &box,const std::string &input,const std::string &help)
+ {
+ }
+ //=========================================================================
+
+ //=========================================================================
+ void BBPInterpreter::commandOutput(const std::string &name,const std::string &box,const std::string &output,const std::string &help)
+ {
+ }
+ //=========================================================================
+
+
+ //=========================================================================
+ /// sets the input of the box with the value
+ void BBPInterpreter::commandSet(const std::string &box,const std::string &input,const std::string &value) // virtual
+ {
+ }
+ //=========================================================================
+
+
+ //=========================================================================
+ void BBPInterpreter::commandDefine(const std::string &name,const std::string &pack,const std::string &scriptfilename) // virtual
+ {
+ this->boxName = name;
+ }
+ //=========================================================================
+
+
+ //=========================================================================
+ void BBPInterpreter::commandEndDefine() // virtual
+ {
+ }
+ //=========================================================================
+
+
+ //=========================================================================
+ void BBPInterpreter::commandExec(const std::string &word) // virtual
+ {
+ }
+ //=========================================================================
+
+
+ //=========================================================================
+ void BBPInterpreter::commandAuthor(const std::string &author) // virtual
+ {
+ }
+ //=========================================================================
+
+ //=========================================================================
+ void BBPInterpreter::commandCategory(const std::string &categorytype) // virtual
+ {
+ }
+ //=========================================================================
+
+ //=========================================================================
+ void BBPInterpreter::commandDescription(const std::string &description) // virtual
+ {
+ }
+ //=========================================================================
+
+} // EO namespace bbtk
+
+// EOF
+
--- /dev/null
+/*
+# ---------------------------------------------------------------------
+#
+# Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
+# pour la Santé)
+# Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
+#
+# 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.
+# ------------------------------------------------------------------------
+*/
+
+/*=========================================================================
+Program: bbtk
+Module: $RCSfile$
+Language: C++
+Date: $Date$
+Version: $Revision$
+=========================================================================*/
+
+
+#ifndef __bbtkBBPInterpreter_h__
+#define __bbtkBBPInterpreter_h__
+
+//Includes bbtk
+#include "bbtkInterpreterVirtual.h"
+
+//Includes std
+#include <iostream>
+#include <set>
+
+
+//#include "bbtkSystem.h"
+//#include "bbtkComplexBlackBox.h"
+
+namespace bbtk
+{
+ class BBPInterpreter : public InterpreterVirtual
+ {
+ public:
+ static Pointer New();
+ BBPInterpreter();
+ ~BBPInterpreter();
+
+ //Public methods
+
+ virtual void commandNew( const std::string& boxType, const std::string& boxName);
+
+ virtual void commandConnection (const std::string &boxfrom,
+ const std::string &output,
+ const std::string &boxto,
+ const std::string &input);
+ virtual void commandSet(const std::string &box,const std::string &input,const std::string &value);
+
+
+ virtual void commandDefine(const std::string &name,const std::string &pack,const std::string &scriptfilename);
+ virtual void commandEndDefine();
+
+ virtual void commandExec(const std::string &word);
+
+ virtual void commandAuthor(const std::string &author);
+ virtual void commandCategory(const std::string &categorytype);
+ virtual void commandDescription(const std::string &description);
+
+ virtual void commandInput(const std::string &name,const std::string &box,const std::string &input,const std::string &help);
+ virtual void commandOutput(const std::string &name,const std::string &box,const std::string &output,const std::string &help);
+
+ std::string boxName;
+ std::set<std::string> dependencies;
+
+ private:
+
+ //Private Attributes
+
+ //Private Methods
+
+ protected:
+
+ //Protected Attributes
+
+ //Protected methods
+
+ };
+}
+// namespace bbtk
+#endif
+