// Copyright (C) 2001 Jean-Marc Valin #include "UINodeRepository.h" #include "path.h" #include #include #include "BaseException.h" #include "UINetwork.h" /*This bunch of includes is for searching directories, maybe there's a better way...*/ #include #ifndef WIN32 #include #endif #include #include #include #include //@implements UIClasses using namespace std; namespace FD { ostream& operator<< (ostream &out, const ItemInfo &iInfo) { out<<"\tname: "< > &UINodeRepository::ModuleDepend() { static map > dep; return dep; } map > &UINodeRepository::FileDepend() { static map > dep; return dep; } map > &UINodeRepository::HeaderDepend() { static map > dep; return dep; } void UINodeRepository::Scan() { cerr<<"UINodeRepository::Scan()"< dirs = envList("FLOWDESIGNER_PATH"); for (unsigned int i=0;i::iterator iter = GlobalRepository().info.begin(); iter != GlobalRepository().info.end(); iter++) { cerr<<"**************"<first<<"("<second<<")"<second)< &UINodeRepository::FindFileFromModule(const string &name) { return ModuleDepend()[name]; } set &UINodeRepository::FindModuleFromFile(const string &name) { return FileDepend()[name]; } set &UINodeRepository::FindHeaderFromFile(const string &name) { return HeaderDepend()[name]; } NodeInfo *UINodeRepository::Find(const string &name) { map::iterator found = GlobalRepository().info.find(name); if (found != GlobalRepository().info.end()) return found->second; return NULL; } vector UINodeRepository::Available() { vector allNodes; string nextItem; map::iterator iter = GlobalRepository().info.begin(); while (iter != GlobalRepository().info.end()) { nextItem = string((*iter).second->category) + "***" + string((*iter).first); allNodes.insert(allNodes.end(), nextItem); iter++; } return allNodes; } NodeInfo *UINodeRepository::findNode(const string &name) { map::iterator found = info.find(name); if (found != info.end()) return found->second; found = GlobalRepository().info.find(name); if (found != GlobalRepository().info.end()) return found->second; return NULL; } UINodeRepository::~UINodeRepository() { clean(); } void UINodeRepository::clean() { /* cerr<<"+++repository contains before cleaning: "<::iterator iter = GlobalRepository().info.begin(); iter != GlobalRepository().info.end(); iter++) { cerr<<"**************"<first<<"("<second<<")"<second)<first<second) { //deleting NodeInfo delete iter->second; } info.erase(iter); } } void UINodeRepository::LoadNodeDefInfo(const string &path, const string &name) { string fullname = path + "/" + name; //cerr<<"Loading def :"<children || !doc->children->name) { cerr << "LoadNodeDefInfo: error loading " << fullname << "\n"; xmlFreeDoc (doc); return; } xmlNodePtr root=doc->children; xmlNodePtr node = root->children; while (node != NULL) { string nodeName; if (string((char*)node->name) == "NodeClass") { NodeInfo *my_info = new NodeInfo; my_info->kind=NodeInfo::builtin; char *str_category = (char *)xmlGetProp(node, (xmlChar *)"category"); if (str_category) my_info->category = string(str_category); else my_info->category = "Unknown"; free(str_category); char *sfile = (char *)xmlGetProp(node, (xmlChar *)"source"); if (sfile) my_info->sourceFile= string(sfile); free(sfile); char *req = (char *)xmlGetProp(node, (xmlChar *)"require"); if (req) my_info->requireList = string(req); free(req); //cerr << my_info->sourceFile << ":" << my_info->requireList << endl; nodeName = string((char *)xmlGetProp(node, (xmlChar *)"name")); //cerr<<"inserting into global repository :"<children; while (data != NULL) { string kind = string((char*)data->name); if (kind == "Input") { xmlChar *tmp; ItemInfo *newInfo = new ItemInfo; char *str_name = (char *)xmlGetProp(data, (xmlChar *)"name"); char *str_type = (char *)xmlGetProp(data, (xmlChar *)"type"); if (str_name) { newInfo->name = string(str_name); free(str_name); } if (str_type) { newInfo->type = string(str_type); free(str_type); } tmp = xmlGetProp(data, (xmlChar *)"value"); if (tmp == NULL) newInfo->value = ""; else newInfo->value = string((char *)tmp); tmp = xmlNodeListGetString(doc, data->children, 1); if (tmp == NULL) newInfo->description = "No Description Available."; else newInfo->description = string((char *)tmp); my_info->inputs.insert(my_info->inputs.end(), newInfo); } else if (kind == "Output") { xmlChar *tmp; ItemInfo *newInfo = new ItemInfo; char *str_name = (char *)xmlGetProp(data, (xmlChar *)"name"); char *str_type = (char *)xmlGetProp(data, (xmlChar *)"type"); //FIXME: Check for NULL newInfo->name = string(str_name); newInfo->type = string(str_type); free(str_name); free(str_type); tmp = xmlGetProp(data, (xmlChar *)"value"); if (tmp == NULL) newInfo->value = ""; else newInfo->value = string((char *)tmp); tmp = xmlNodeListGetString(doc, data->children, 1); if (tmp == NULL) newInfo->description = "No Description Available."; else newInfo->description = string((char *)tmp); my_info->outputs.insert(my_info->outputs.end(), newInfo); } else if (kind == "Parameter") { xmlChar *tmp; ItemInfo *newInfo = new ItemInfo; char *str_name = (char *)xmlGetProp(data, (xmlChar *)"name"); char *str_type = (char *)xmlGetProp(data, (xmlChar *)"type"); if (str_name) { newInfo->name = string(str_name); free(str_name); } if (str_type) { newInfo->type = string(str_type); free(str_type); } tmp = xmlGetProp(data, (xmlChar *)"value"); if (tmp == NULL) newInfo->value = ""; else newInfo->value = string((char *)tmp); free(tmp); tmp = xmlNodeListGetString(doc, data->children, 1); if (tmp == NULL) newInfo->description = "No Description Available."; else newInfo->description = string((char *)tmp); free(tmp); my_info->params.insert(my_info->params.end(), newInfo); } else if (kind == "Description") { xmlChar *tmp; tmp = xmlNodeListGetString(doc, data->children, 1); if (tmp == NULL) my_info->description = "No description available"; else my_info->description = string((char *)tmp); free(tmp); } else if (!xmlIsBlankNode(data)) { cerr << "other\n"; } data = data->next; } } /*Dependencies for modules*/ else if (string((char*)node->name) == "ModuleDepend") { char *dep_module = (char *)xmlGetProp(node, (xmlChar *)"module"); if (!dep_module) throw new GeneralException("Empty module dependency", __FILE__, __LINE__); xmlNodePtr depend = node->children; while (depend != NULL) { if (xmlIsBlankNode(depend)) { depend = depend->next; continue; } if (string((char*)depend->name) != "Require") throw new GeneralException(string("Unknown section in module dependency: ") + (char*)node->name, __FILE__, __LINE__); char *req_file = (char *)xmlGetProp(depend, (xmlChar *)"file"); if (!req_file) throw new GeneralException(string("Empty dependency for module: ") + dep_module, __FILE__, __LINE__); ModuleDepend()[dep_module].insert(ModuleDepend()[dep_module].end(), req_file); depend = depend->next; } } /*Dependencies for files*/ else if (string((char*)node->name) == "FileDepend") { char *dep_file = (char *)xmlGetProp(node, (xmlChar *)"file"); if (!dep_file) throw new GeneralException("Empty file dependency", __FILE__, __LINE__); xmlNodePtr depend = node->children; while (depend != NULL) { if (string((char*)depend->name) == "RequireModule") { char *req_module = (char *)xmlGetProp(depend, (xmlChar *)"module"); if (!req_module) throw new GeneralException(string("Empty module dependency for file: ") + dep_file, __FILE__, __LINE__); FileDepend()[dep_file].insert(FileDepend()[dep_file].end(), req_module); } else if (string((char*)depend->name) == "RequireHeader") { char *req_header = (char *)xmlGetProp(depend, (xmlChar *)"header"); if (!req_header) throw new GeneralException(string("Empty header dependency for file: ") + dep_file, __FILE__, __LINE__); HeaderDepend()[dep_file].insert(HeaderDepend()[dep_file].end(), req_header); } else if (!xmlIsBlankNode(depend)) throw new GeneralException(string("Unknown section in file dependency: ") + (char*)node->name, __FILE__, __LINE__); depend = depend->next; } } else if (!xmlIsBlankNode(node)) throw new GeneralException(string("Unknown section in toolbox definition file: ") + string((char*)node->name) + " in " + fullname, __FILE__, __LINE__); node = node->next; } xmlFreeDoc(doc); } void UINodeRepository::LoadExtDocInfo(const string &path, const string &name) { string fullpath = path + "/" + name; string basename = string(name.begin(), name.end()-2); ifstream docFile(fullpath.c_str()); if (docFile.fail()) { cerr << "load: error loading " << fullpath << "\n"; return; } char ch; docFile >> ch; if (ch=='#') { while (ch != '<') { docFile >> ch; if (docFile.fail()) { cerr << "ERROR\n"; return; } } } docFile.putback(ch); string docStr; while(1) { //char buff[1025]; //docFile.read(buff, 1024); //buff[1024]=0; string buff; getline( docFile, buff ); if (docFile.fail()) { //docStr.append(buff, docFile.gcount()); docStr.append(buff.c_str(), docFile.gcount()); break; } //docStr.append(buff, 1024); docStr.append(buff.c_str()); } xmlDocPtr doc = xmlParseMemory (const_cast (docStr.c_str()), docStr.size()); //xmlDocPtr doc = xmlParseFile(fullname.c_str()); if (!doc || !doc->children || !doc->children->name) { cerr << "ExtDoc: error loading " << fullpath << "\n"; xmlFreeDoc (doc); return; } GlobalRepository().loadDocInfo(doc, basename); } void UINodeRepository::loadDocInfo(xmlDocPtr doc, const string &basename) { map &externalDocInfo = GlobalRepository().info; if (externalDocInfo.find(basename) != externalDocInfo.end()) { cerr << "error: net " << basename << " already existed\n"; return; } //cerr << "new subnet info with name: " << netName << "\n"; NodeInfo *my_info = new NodeInfo; my_info->kind = NodeInfo::external; //cerr<<"Inserting external info : "<children; xmlChar *category = xmlGetProp(root, (xmlChar *)"category"); if (category) { my_info->category = string((char *)category); free (category); } xmlNodePtr net = root->children; while (net != NULL) { //cerr << "scanning networks...\n"; if (string((char*)net->name) == "Network") { //cerr << "scanning a net\n"; string netName = string((char *)xmlGetProp(net, (xmlChar *)"name")); if (netName == "MAIN") { //loadNetInfo(net, externalDocInfo, basename); xmlNodePtr node = net->children; while (node != NULL) { if (string((char*)node->name) == "NetInput") { string termName = string((char *)xmlGetProp(node, (xmlChar *)"name")); ItemInfo *newInfo = new ItemInfo; newInfo->name = termName; my_info->inputs.insert (my_info->inputs.end(), newInfo); } else if (string((char*)node->name) == "NetOutput") { string termName = string((char *)xmlGetProp(node, (xmlChar *)"name")); ItemInfo *newInfo = new ItemInfo; newInfo->name = termName; my_info->outputs.insert (my_info->outputs.end(), newInfo); } node = node->next; } } } else if (string((char*)net->name) == "Parameter") { char *param_name = (char *)xmlGetProp(net, (xmlChar *)"name"); char *param_type = (char *)xmlGetProp(net, (xmlChar *)"type"); char *param_value = (char *)xmlGetProp(net, (xmlChar *)"value"); if (param_name && param_type) { ItemInfo *newInfo = new ItemInfo; newInfo->name = param_name; if (string(param_type)=="") newInfo->type = "int"; else newInfo->type = param_type; if (string(param_value)!="") newInfo->value = param_value; my_info->params.insert (my_info->params.end(), newInfo); } //cerr << "param\n"; } net = net->next; } xmlFreeDoc(doc); } void UINodeRepository::LoadAllInfoRecursive(const string &path) { struct stat my_stat; DIR *my_directory = opendir (path.c_str()); if (!my_directory) return; struct dirent *current_entry; for (current_entry = readdir(my_directory); current_entry != NULL; current_entry = readdir(my_directory)) { string name = current_entry->d_name; #ifndef WIN32 string fullpath = path + string("/") + name; #else string fullpath = path + string("\\") + name; #warning Please remove this debug line. cerr<<"UINodeRepository::LoadAllInfoRecursive with full path : "<d_name); if (len > 2 && strcmp(".n", current_entry->d_name + len-2)==0) { //cerr<<"Loading network : "< 4 && strcmp(".def", current_entry->d_name + len-4)==0) { #ifdef WIN32 #warning Please remove this debug line. cerr<<"Loading toolbox : "<name) == "Network") { loadNetInfo(net); } net = net->next; } } void UINodeRepository::loadNetInfo(xmlNodePtr net) { char *str_netName = (char *)xmlGetProp(net, (xmlChar *)"name"); string netName = string(str_netName); free(str_netName); xmlChar *category = xmlGetProp(net, (xmlChar *)"category"); if (info.find(netName) != info.end()) { cerr << "error: net " << netName << " already existed\n"; return; } //cerr << "new subnet info with name: " << netName << "\n"; NodeInfo *ninfo = new NodeInfo; ninfo->kind = NodeInfo::subnet; //we are dealing with a local repository, in a document info[netName] = ninfo; if (category) { ninfo->category = string((char *)category); free(category); } //cerr << "scan all nodes\n"; xmlNodePtr node = net->children; while (node != NULL) { if (string((char*)node->name) == "Node") { xmlNodePtr par = node->children; //cerr << "par = " << par << endl; while (par) { if (string((char*)par->name) == "Parameter") { char *str_paramName = (char *) xmlGetProp(par, (xmlChar *)"value"); char *str_type = (char *) xmlGetProp(par, (xmlChar *)"type"); string paramName = string (str_paramName); string type = string (str_type); free(str_paramName); free(str_type); if (type == "subnet_param") { bool alreadyPresent = false; for (unsigned int j=0;jparams.size();j++) if (ninfo->params[j]->name == paramName) alreadyPresent=true; if (!alreadyPresent) { ItemInfo *newInfo = new ItemInfo; newInfo->name = paramName; //FIXME: This always sets the type to subnet_info, which is incorrect newInfo->type = type; ninfo->params.insert (ninfo->params.end(), newInfo); } } } par = par->next; } //check for params } node = node->next; } //checking for the network type, we are interested in //iterators and threaded iterators here, nothing to do with subnets xmlChar *type = xmlGetProp(net, (xmlChar *)"type"); if (type) { if (string((char*)type)=="iterator") { ItemInfo *newInfo = new ItemInfo; newInfo->name = "DOWHILE"; newInfo->type = "bool"; ninfo->params.insert (ninfo->params.end(), newInfo); free(type); } else if (string((char*)type)=="threaded") { ItemInfo *newInfo = new ItemInfo; newInfo->name = "RATE_PER_SECOND"; newInfo->type = "int"; ninfo->params.insert (ninfo->params.end(), newInfo); free(type); } } //check for network description char *desc = (char *) xmlGetProp(net, (xmlChar *)"description"); if (desc) { //set description ninfo->description = string(desc); //free XML string free(desc); } //scan all net inputs/outputs node = net->children; while (node != NULL) { if (string((char*)node->name) == "NetInput") { char *str_name = (char *)xmlGetProp(node, (xmlChar *)"name"); char *str_type = (char *)xmlGetProp(node, (xmlChar *)"object_type"); char *str_desc = (char *)xmlGetProp(node, (xmlChar *)"description"); string termName = string(str_name); string termType = "any"; string termDescription = "No description available"; //Free XML strings free(str_name); if (str_type) { termType = str_type; free(str_type); } if (str_desc) { termDescription = str_desc; free(str_desc); } ItemInfo *newInfo = new ItemInfo; newInfo->name = termName; newInfo->type = termType; newInfo->description = termDescription; ninfo->inputs.insert (ninfo->inputs.end(), newInfo); } else if (string((char*)node->name) == "NetOutput") { char *str_name = (char *)xmlGetProp(node, (xmlChar *)"name"); char *str_type = (char *)xmlGetProp(node, (xmlChar *)"object_type"); char *str_desc = (char *)xmlGetProp(node, (xmlChar *)"description"); string termName = string(str_name); string termType = "any"; string termDescription = "No description available"; free(str_name); if (str_type) { termType = str_type; free(str_type); } if (str_desc) { termDescription = str_desc; free(str_desc); } ItemInfo *newInfo = new ItemInfo; newInfo->name = termName; newInfo->type = termType; newInfo->description = termDescription; ninfo->outputs.insert (ninfo->outputs.end(), newInfo); } node = node->next; } } void UINodeRepository::ProcessDependencies(set &initial_files, bool toplevel) { unsigned int nbDepends = initial_files.size(); //Process module/file dependencies, loop until there's nothing else to add do { nbDepends = initial_files.size(); set addMod; //Core is always necessary and we'll save a bunch of @require core addMod.insert(addMod.begin(), "core"); //Scan all files in required list to find all required modules set::iterator file=initial_files.begin(); while (file != initial_files.end()) { if (FileDepend().find(*file) != FileDepend().end()) { set &moduleDep = FileDepend()[*file]; set::iterator mod = moduleDep.begin(); while (mod != moduleDep.end()) { addMod.insert(addMod.end(), *mod); mod++; } } file++; } //Scan all modules in required list to find all required files set::iterator mod=addMod.begin(); while (mod != addMod.end()) { if (ModuleDepend().find(*mod) != ModuleDepend().end()) { set &fileDep = ModuleDepend()[*mod]; set::iterator file = fileDep.begin(); while (file != fileDep.end()) { initial_files.insert(initial_files.end(), *file); file++; } } mod++; } } while (nbDepends != initial_files.size()); //Repeat recursivly until there's nothing else to add //if (nbDepends != initial_files.size()) // processDependencies(initial_files, false); //Process header dependencies, loop until there's nothing else to add do { nbDepends = initial_files.size(); if (toplevel) { set::iterator file=initial_files.begin(); while (file != initial_files.end()) { if (HeaderDepend().find(*file) != HeaderDepend().end()) { set &headerDep = HeaderDepend()[*file]; set::iterator header = headerDep.begin(); while (header != headerDep.end()) { initial_files.insert(initial_files.end(), *header); header++; } } file++; } } } while (nbDepends != initial_files.size()); } void UINodeRepository::updateNetInfo(UINetwork *net) { iterator inet = info.find(net->getName()); if (inet!=info.end()) { //cerr<<"UINodeRepository deleting network info:"<getName()<second; } NodeInfo *ninfo = new NodeInfo; vector my_terminals = net->getTerminals(); //updating inputs & outputs //new implementation using name + type + description for all UINetTerminals //(DL) 15/12/203 for (unsigned int i = 0; i < my_terminals.size(); i++) { ItemInfo *newInfo = new ItemInfo; if (my_terminals[i]) { //input name newInfo->name = my_terminals[i]->getName(); //input type newInfo->type = my_terminals[i]->getType(); //input description newInfo->description = my_terminals[i]->getDescription(); //input our output? if (my_terminals[i]->getType() == UINetTerminal::INPUT) { ninfo->inputs.push_back(newInfo); } else if (my_terminals[i]->getType() == UINetTerminal::OUTPUT) { ninfo->outputs.push_back(newInfo); } } } //cerr<<"insertingNetParams"<insertNetParams(ninfo->params); ninfo->category = "Subnet"; //Description is now stored in a network definition ninfo->description = net->getDescription(); //cerr<<"updated network info for "<getName()<getName()] = ninfo; } }//namespace FD