view_ctl.cpp (8761B)
1 /** 2 * @file 3 * @brief Interface to the View database. 4 */ 5 6 #include <cstddef> 7 #include <iostream> 8 #include <sstream> 9 #include <stdexcept> 10 #include <string> 11 #include <vector> 12 13 #include <boost/archive/binary_oarchive.hpp> 14 #include <boost/make_shared.hpp> 15 #include <boost/program_options.hpp> 16 #include <boost/shared_ptr.hpp> 17 #include <sqlite3.h> 18 19 #include "factory.hpp" 20 #include "nmlp_iostream_exports.hpp" 21 #include "sqlite_utils.hpp" 22 #include "view.hpp" 23 24 static char const * const usage = "usage:\n" 25 "\tview_ctl --help\n" 26 "\tview_ctl add --interactive -d database\n" 27 "\tview_ctl add name configfile -d database\n" 28 "\tview_ctl del name -d database\n" 29 "\tview_ctl list -d database\n"; 30 31 /** @brief Construct a View interactively. */ 32 boost::shared_ptr<View> interactive_build_view(); 33 34 /** @brief Construct a View from a configuration file. */ 35 boost::shared_ptr<View> detached_build_view(std::string const &name, std::string const &config_path); 36 37 /** @brief Insert a View into a given database. */ 38 void add_view(std::string const &database_path, boost::shared_ptr<View> view); 39 40 /** @brief Delete a View from a given database. */ 41 void del_view(std::string const &database_path, std::string const &name); 42 43 /** @brief List the View of a given database. */ 44 void list_view(std::string const &database_path); 45 46 int main(int argc, char **argv){ 47 namespace po = boost::program_options; 48 std::string database_path; 49 50 po::options_description desc("Allowed options"); 51 desc.add_options() 52 ("command,a", po::value<std::string>(), "Select the operation to execute") 53 ("configfile,c", po::value<std::string>(), "Configuration file containing a view description") 54 ("database,d", po::value<std::string>(&database_path), "Select the target view database") 55 ("help,h", "Print a summary of the options") 56 ("interactive,i", "Start in interactive mode") 57 ("name,n", po::value<std::string>(), "Name of the view to add/delete") 58 ; 59 60 po::positional_options_description p; 61 p.add("command", 1).add("name", 1).add("configfile", 1); 62 63 po::variables_map vm; 64 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm); 65 po::notify(vm); 66 67 if(vm.count("help")){ 68 std::cout << usage << "\n" << desc << "\n"; 69 return 0; 70 } 71 72 if(!vm.count("database")){ 73 std::cout << usage; 74 return 1; 75 } 76 77 if(vm["command"].as<std::string>()=="add"){ 78 if(vm.count("interactive")) 79 add_view(database_path, interactive_build_view()); 80 else { 81 if(!vm.count("name") || !vm.count("configfile")){ 82 std::cout << usage; 83 return 1; 84 } 85 add_view(database_path, detached_build_view(vm["name"].as<std::string>(), vm["configfile"].as<std::string>())); 86 } 87 } else if(vm["command"].as<std::string>()=="del"){ 88 if(!vm.count("name")){ 89 std::cout << usage; 90 return 1; 91 } 92 del_view(database_path, vm["name"].as<std::string>()); 93 } else if(vm["command"].as<std::string>()=="list"){ 94 list_view(database_path); 95 } 96 } 97 98 boost::shared_ptr<View> interactive_build_view(){ 99 boost::shared_ptr<View> view=boost::make_shared<View>(); 100 101 std::string name; 102 std::cout << "Name? "; 103 std::getline(std::cin, name); 104 view->name=name; 105 106 std::string kind; 107 std::cout << "Kind? "; 108 std::getline(std::cin, kind); 109 view->kind=kind; 110 111 std::cout << "Description? "; 112 std::string description; 113 std::getline(std::cin, description); 114 view->description=description; 115 116 std::cout << "View space dimension? "; 117 std::size_t view_dimension; 118 std::cin >> view_dimension; 119 view->view_dimension=view_dimension; 120 121 std::cout << "Concept space dimension? "; 122 std::size_t concept_dimension; 123 std::cin >> concept_dimension; 124 view->concept_dimension=concept_dimension; 125 126 std::cout << "########################\n"; 127 std::cout << "### Encoder creation ###\n"; 128 std::cout << "########################\n"; 129 view->encoder=interactive_module_factory(std::cin, std::cout, view_dimension, concept_dimension); 130 131 std::cout << "########################\n"; 132 std::cout << "### Decoder creation ###\n"; 133 std::cout << "########################\n"; 134 view->decoder=interactive_module_factory(std::cin, std::cout, concept_dimension, view_dimension); 135 136 return view; 137 } 138 139 boost::shared_ptr<View> detached_build_view(std::string const &name, std::string const &config_path){ 140 namespace po = boost::program_options; 141 142 po::options_description desc("Config file options"); 143 desc.add_options() 144 ("kind", po::value<std::string>(), "Set the kind of view to be created") 145 ("description", po::value<std::string>(), "Set the description of the view") 146 ("view_dimension", po::value<std::size_t>(), "Set the dimension of the viewed space") 147 ("concept_dimension", po::value<std::size_t>(), "Set the dimension of the concept space") 148 ("encoder.module", po::value<std::vector<std::string> >(), "Add a module to the encoder") 149 ("encoder.size", po::value<std::vector<std::size_t> >(), "Set the output size of the last encoder Linear module") 150 ("encoder.variance", po::value<std::vector<float> >(), "Set the variance of the last encoder Linear module") 151 ("decoder.module", po::value<std::vector<std::string> >(), "Add a module to the decoder") 152 ("decoder.size", po::value<std::vector<std::size_t> >(), "Set the output size of the last decoder Linear module") 153 ("decoder.variance", po::value<std::vector<float> >(), "Set the variance of the last decoder Linear module") 154 ; 155 156 po::variables_map vm; 157 po::store(po::parse_config_file<char>(config_path.c_str(), desc, false), vm); 158 po::notify(vm); 159 160 boost::shared_ptr<View> view=boost::make_shared<View>(); 161 162 if(!vm.count("kind")) 163 throw std::runtime_error("Missing 'kind' option in configuration file"); 164 if(!vm.count("description")) 165 throw std::runtime_error("Missing 'description' option in configuration file"); 166 if(!vm.count("view_dimension")) 167 throw std::runtime_error("Missing 'view_dimension' option in configuration file"); 168 if(!vm.count("concept_dimension")) 169 throw std::runtime_error("Missing 'concept_dimension' option in configuration file"); 170 171 view->name=name; 172 view->kind=vm["kind"].as<std::string>(); 173 view->description=vm["description"].as<std::string>(); 174 view->view_dimension=vm["view_dimension"].as<std::size_t>(); 175 view->concept_dimension=vm["concept_dimension"].as<std::size_t>(); 176 177 view->encoder=detached_module_factory(vm, "encoder.", view->view_dimension, view->concept_dimension); 178 view->decoder=detached_module_factory(vm, "decoder.", view->concept_dimension, view->view_dimension); 179 180 return view; 181 } 182 183 void add_view(std::string const &database_path, boost::shared_ptr<View> view){ 184 /// @todo Can it be optimised? 185 std::stringstream buf; 186 boost::archive::binary_oarchive oa(buf); 187 oa << view; 188 std::string bufstr=buf.str(); 189 190 DB_connection connection(database_path); 191 sqlite3_stmt *stmt; 192 193 std::stringstream ss; 194 ss << "INSERT INTO views VALUES (" 195 << "'" << view->name << "'," 196 << "'" << view->kind << "'," 197 << "'" << view->description << "'," 198 << "?)"; 199 std::string sql=ss.str(); 200 201 int err=sqlite3_prepare_v2(connection.handle, sql.c_str(), sql.size()+1, &stmt, 0); 202 DB_statement statement(stmt); 203 if(err!=SQLITE_OK) 204 throw std::runtime_error(sqlite3_errmsg(connection.handle)); 205 206 if(sqlite3_bind_blob(stmt, 1, bufstr.c_str(), bufstr.size(), SQLITE_STATIC)!=SQLITE_OK) 207 throw std::runtime_error(sqlite3_errmsg(connection.handle)); 208 209 if(sqlite3_step(stmt)!=SQLITE_DONE) 210 throw std::runtime_error(sqlite3_errmsg(connection.handle)); 211 } 212 213 void del_view(std::string const &database_path, const std::string &name){ 214 DB_connection connection(database_path); 215 sqlite3_stmt *stmt; 216 217 std::stringstream ss; 218 ss << "DELETE FROM views WHERE name='" << name << "'"; 219 std::string sql=ss.str(); 220 221 int err=sqlite3_prepare_v2(connection.handle, sql.c_str(), sql.size()+1, &stmt, 0); 222 DB_statement statement(stmt); 223 if(err!=SQLITE_OK) 224 throw std::runtime_error(sqlite3_errmsg(connection.handle)); 225 226 if(sqlite3_step(stmt)!=SQLITE_DONE) 227 throw std::runtime_error(sqlite3_errmsg(connection.handle)); 228 } 229 230 void list_view(std::string const &database_path){ 231 DB_connection connection(database_path); 232 sqlite3_stmt *stmt; 233 234 std::stringstream ss; 235 ss << "SELECT name, kind, description FROM views"; 236 std::string sql=ss.str(); 237 238 int err=sqlite3_prepare_v2(connection.handle, sql.c_str(), sql.size()+1, &stmt, 0); 239 DB_statement statement(stmt); 240 if(err!=SQLITE_OK) 241 throw std::runtime_error(sqlite3_errmsg(connection.handle)); 242 243 while((err=sqlite3_step(stmt))!=SQLITE_DONE){ 244 if(err!=SQLITE_ROW) 245 throw std::runtime_error(sqlite3_errmsg(connection.handle)); 246 std::cout << sqlite3_column_text(stmt, 0) << " (" << sqlite3_column_text(stmt, 1) << ")\n" 247 << "\t" << sqlite3_column_text(stmt, 2) << "\n\n"; 248 } 249 } 250