/** * * create_controller.cc * An Tao * * Copyright 2018, An Tao. All rights reserved. * https://github.com/an-tao/drogon * Use of this source code is governed by a MIT license * that can be found in the License file. * * Drogon * */ #include "create_controller.h" #include "cmd.h" #include #include #include #include #include using namespace drogon_ctl; void create_controller::handleCommand(std::vector ¶meters) { // std::cout<<"create!"< 1) { std::cerr << "Too many parameters" << std::endl; exit(1); } auto className = parameters[0]; createARestfulController(className, resource); } } void create_controller::newSimpleControllerHeaderFile( std::ofstream &file, const std::string &className) { file << "#pragma once\n"; file << "#include \n"; file << "using namespace drogon;\n"; std::string class_name = className; std::string namepace_path = "/"; auto pos = class_name.find("::"); size_t namespaceCount = 0; while (pos != std::string::npos) { ++namespaceCount; auto namespaceName = class_name.substr(0, pos); class_name = class_name.substr(pos + 2); file << "namespace " << namespaceName << "\n"; namepace_path.append(namespaceName).append("/"); file << "{\n"; pos = class_name.find("::"); } file << "class " << class_name << ":public drogon::HttpSimpleController<" << class_name << ">\n"; file << "{\n"; file << " public:\n"; file << " virtual void asyncHandleHttpRequest(const HttpRequestPtr& " "req, std::function &&callback) " "override;\n"; file << " PATH_LIST_BEGIN\n"; file << " //list path definitions here;\n"; file << " " "//PATH_ADD(\"/" "path\",\"filter1\",\"filter2\",HttpMethod1,HttpMethod2...);\n"; file << " PATH_LIST_END\n"; file << "};\n"; while (namespaceCount > 0) { --namespaceCount; file << "}\n"; } } void create_controller::newSimpleControllerSourceFile( std::ofstream &file, const std::string &className, const std::string &filename) { file << "#include \"" << filename << ".h\"\n"; auto pos = className.rfind("::"); auto class_name = className; if (pos != std::string::npos) { auto namespacename = className.substr(0, pos); file << "using namespace " << namespacename << ";\n"; class_name = className.substr(pos + 2); } file << "void " << class_name << "::asyncHandleHttpRequest(const HttpRequestPtr& req, " "std::function &&callback)\n"; file << "{\n"; file << " //write your application logic here\n"; file << "}"; } void create_controller::newWebsockControllerHeaderFile( std::ofstream &file, const std::string &className) { file << "#pragma once\n"; file << "#include \n"; file << "using namespace drogon;\n"; std::string class_name = className; std::string namepace_path = "/"; auto pos = class_name.find("::"); size_t namespaceCount = 0; while (pos != std::string::npos) { ++namespaceCount; auto namespaceName = class_name.substr(0, pos); class_name = class_name.substr(pos + 2); file << "namespace " << namespaceName << "\n"; namepace_path.append(namespaceName).append("/"); file << "{\n"; pos = class_name.find("::"); } file << "class " << class_name << ":public drogon::WebSocketController<" << class_name << ">\n"; file << "{\n"; file << " public:\n"; file << " virtual void handleNewMessage(const WebSocketConnectionPtr&,\n"; file << " std::string &&,\n"; file << " const WebSocketMessageType &) " "override;\n"; file << " virtual void handleNewConnection(const HttpRequestPtr &,\n"; file << " const " "WebSocketConnectionPtr&)override;\n"; file << " virtual void handleConnectionClosed(const " "WebSocketConnectionPtr&)override;\n"; file << " WS_PATH_LIST_BEGIN\n"; file << " //list path definitions here;\n"; file << " //WS_PATH_ADD(\"/path\",\"filter1\",\"filter2\",...);\n"; file << " WS_PATH_LIST_END\n"; file << "};\n"; while (namespaceCount > 0) { --namespaceCount; file << "}\n"; } } void create_controller::newWebsockControllerSourceFile( std::ofstream &file, const std::string &className, const std::string &filename) { file << "#include \"" << filename << ".h\"\n"; auto pos = className.rfind("::"); auto class_name = className; if (pos != std::string::npos) { auto namespacename = className.substr(0, pos); file << "using namespace " << namespacename << ";\n"; class_name = className.substr(pos + 2); } file << "void " << class_name << "::handleNewMessage(const WebSocketConnectionPtr& wsConnPtr, " "std::string &&message, const WebSocketMessageType &type)\n"; file << "{\n"; file << " //write your application logic here\n"; file << "}\n"; file << "void " << class_name << "::handleNewConnection(const HttpRequestPtr &req,const " "WebSocketConnectionPtr& wsConnPtr)\n"; file << "{\n"; file << " //write your application logic here\n"; file << "}\n"; file << "void " << class_name << "::handleConnectionClosed(const WebSocketConnectionPtr& " "wsConnPtr)\n"; file << "{\n"; file << " //write your application logic here\n"; file << "}\n"; } void create_controller::newHttpControllerHeaderFile( std::ofstream &file, const std::string &className) { file << "#pragma once\n"; file << "#include \n"; file << "using namespace drogon;\n"; std::string class_name = className; std::string namepace_path = "/"; auto pos = class_name.find("::"); size_t namespaceCount = 0; while (pos != std::string::npos) { ++namespaceCount; auto namespaceName = class_name.substr(0, pos); class_name = class_name.substr(pos + 2); file << "namespace " << namespaceName << "\n"; namepace_path.append(namespaceName).append("/"); file << "{\n"; pos = class_name.find("::"); } file << "class " << class_name << ":public drogon::HttpController<" << class_name << ">\n"; file << "{\n"; file << " public:\n"; file << " METHOD_LIST_BEGIN\n"; file << " //use METHOD_ADD to add your custom processing function " "here;\n"; file << " //METHOD_ADD(" << class_name << "::get,\"/{2}/{1}\",Get);" "//path is " << namepace_path << class_name << "/{arg2}/{arg1}\n"; file << " //METHOD_ADD(" << class_name << "::your_method_name,\"/{1}/{2}/list\",Get);" "//path is " << namepace_path << class_name << "/{arg1}/{arg2}/list\n"; file << " //ADD_METHOD_TO(" << class_name << "::your_method_name,\"/absolute/path/{1}/{2}/list\",Get);" "//path is /absolute/path/{arg1}/{arg2}/list\n"; file << "\n"; file << " METHOD_LIST_END\n"; file << " // your declaration of processing function maybe like this:\n"; file << " // void get(const HttpRequestPtr& req," "std::function &&callback,int " "p1,std::string p2);\n"; file << " // void your_method_name(const HttpRequestPtr& req," "std::function &&callback,double " "p1,int p2) const;\n"; file << "};\n"; while (namespaceCount > 0) { --namespaceCount; file << "}\n"; } } void create_controller::newHttpControllerSourceFile( std::ofstream &file, const std::string &className, const std::string &filename) { file << "#include \"" << filename << ".h\"\n"; auto pos = className.rfind("::"); auto class_name = className; if (pos != std::string::npos) { auto namespacename = className.substr(0, pos); file << "using namespace " << namespacename << ";\n"; class_name = className.substr(pos + 2); } file << "//add definition of your processing function here\n"; } void create_controller::createController(std::vector &httpClasses, ControllerType type) { for (auto iter = httpClasses.begin(); iter != httpClasses.end(); ++iter) { if ((*iter)[0] == '-') { std::cout << ARGS_ERROR_STR << std::endl; return; } } for (auto const &className : httpClasses) { createController(className, type); } } void create_controller::createController(const std::string &className, ControllerType type) { std::regex regex("::"); std::string ctlName = std::regex_replace(className, regex, std::string("_")); std::string headFileName = ctlName + ".h"; std::string sourceFilename = ctlName + ".cc"; { std::ifstream iHeadFile(headFileName.c_str(), std::ifstream::in); std::ifstream iSourceFile(sourceFilename.c_str(), std::ifstream::in); if (iHeadFile || iSourceFile) { std::cout << "The file you want to create already exists, " "overwrite it(y/n)?" << std::endl; auto in = getchar(); (void)getchar(); // get the return key if (in != 'Y' && in != 'y') { std::cout << "Abort!" << std::endl; exit(0); } } } std::ofstream oHeadFile(headFileName.c_str(), std::ofstream::out); std::ofstream oSourceFile(sourceFilename.c_str(), std::ofstream::out); if (!oHeadFile || !oSourceFile) { perror(""); exit(1); } if (type == Http) { std::cout << "create a http controller:" << className << std::endl; newHttpControllerHeaderFile(oHeadFile, className); newHttpControllerSourceFile(oSourceFile, className, ctlName); } else if (type == Simple) { std::cout << "create a http simple controller:" << className << std::endl; newSimpleControllerHeaderFile(oHeadFile, className); newSimpleControllerSourceFile(oSourceFile, className, ctlName); } else if (type == WebSocket) { std::cout << "create a websocket controller:" << className << std::endl; newWebsockControllerHeaderFile(oHeadFile, className); newWebsockControllerSourceFile(oSourceFile, className, ctlName); } } void create_controller::createARestfulController(const std::string &className, const std::string &resource) { std::regex regex("::"); std::string ctlName = std::regex_replace(className, regex, std::string("_")); std::string headFileName = ctlName + ".h"; std::string sourceFilename = ctlName + ".cc"; { std::ifstream iHeadFile(headFileName.c_str(), std::ifstream::in); std::ifstream iSourceFile(sourceFilename.c_str(), std::ifstream::in); if (iHeadFile || iSourceFile) { std::cout << "The file you want to create already exists, " "overwrite it(y/n)?" << std::endl; auto in = getchar(); (void)getchar(); // get the return key if (in != 'Y' && in != 'y') { std::cout << "Abort!" << std::endl; exit(0); } } } std::ofstream oHeadFile(headFileName.c_str(), std::ofstream::out); std::ofstream oSourceFile(sourceFilename.c_str(), std::ofstream::out); if (!oHeadFile || !oSourceFile) { perror(""); exit(1); } auto v = utils::splitString(className, "::"); drogon::DrTemplateData data; data.insert("className", v[v.size() - 1]); v.pop_back(); data.insert("namespaceVector", v); data.insert("resource", resource); data.insert("fileName", ctlName); if (resource.empty()) { data.insert("ctlCommand", std::string("drogon_ctl create controller -r ") + className); } else { data.insert("ctlCommand", std::string("drogon_ctl create controller -r ") + className + " --resource=" + resource); } try { auto templ = DrTemplateBase::newTemplate("restful_controller_h.csp"); oHeadFile << templ->genText(data); templ = DrTemplateBase::newTemplate("restful_controller_cc.csp"); oSourceFile << templ->genText(data); } catch (const std::exception &err) { std::cerr << err.what() << std::endl; exit(1); } std::cout << "create a http restful API controller:" << className << std::endl; std::cout << "file name: " << ctlName << ".h and " << ctlName << ".cc" << std::endl; }