#include "BatchMakeUtilities.h" #include "ModuleParameterGroup.h" #include "ModuleParameter.h" #include #include #include std::string GenerateBatchMakeWrapper(const ModuleDescription& module) { std::ostringstream wrapper; std::string indent1(" "); std::string indent2 = indent1 + indent1; std::string indent3 = indent2 + indent1; std::string indent4 = indent3 + indent1; // Can only generate BatchMakeWrappers for executables. if (module.GetType() != "CommandLineModule") { return ""; } // BatchMake only understands parameter types: // file=0, bool=1, int=2, float=3, string=4, enum=5 // // Map what we can into these. // typedef std::map ModuleParameterToBatchMakeTypeMap; ModuleParameterToBatchMakeTypeMap mp2bm; mp2bm["integer"] = "2"; // int mp2bm["float"] = "3"; // float mp2bm["double"] = "3"; // float mp2bm["boolean"] = "1"; // bool mp2bm["string"] = "4"; // string mp2bm["integer-vector"] = "4"; // string mp2bm["float-vector"] = "4"; // string mp2bm["double-vector"] = "4"; // string mp2bm["string-vector"] = "4"; // string mp2bm["integer-enumeration"] = "5"; // enum mp2bm["float-enumeration"] = "3"; // float ??? mp2bm["double-enumeration"] = "3"; // float ??? mp2bm["string-enumeration"] = "4"; // string ??? mp2bm["file"] = "0"; // file mp2bm["directory"] = "0"; // file ??? mp2bm["image"] = "0"; // file mp2bm["geometry"] = "0"; // file mp2bm["point"] = "4"; // string ??? // BatchMake format preamble wrapper << "" << std::endl; wrapper << "" << std::endl; wrapper << indent1 << "1.0" << std::endl; wrapper << indent1 << "" << std::endl; wrapper << indent2 << "" << module.GetTitle() << "" << std::endl; wrapper << indent2 << "" << module.GetVersion() << "" << std::endl; wrapper << indent2 << "" << module.GetLocation() << "" << std::endl; wrapper << indent2 << "" << std::endl; std::vector::const_iterator pgbeginit = module.GetParameterGroups().begin(); std::vector::const_iterator pgendit = module.GetParameterGroups().end(); std::vector::const_iterator pgit; ModuleParameterToBatchMakeTypeMap::iterator mp2bmIt; // Loop over all parameters that have a flag then loop over the // parameters that are index parameters // // Loop over executables with flags int pcount = 0; for (pgit = pgbeginit; pgit != pgendit; ++pgit) { // iterate over each parameter in this group std::vector::const_iterator pbeginit = (*pgit).GetParameters().begin(); std::vector::const_iterator pendit = (*pgit).GetParameters().end(); std::vector::const_iterator pit; for (pit = pbeginit; pit != pendit; ++pit) { std::string prefix; std::string flag; bool hasFlag = false; if ((*pit).GetLongFlag() != "") { prefix = "--"; flag = (*pit).GetLongFlag(); hasFlag = true; } else if ((*pit).GetFlag() != "") { prefix = "-"; flag = (*pit).GetFlag(); hasFlag = true; } if (hasFlag) { pcount++; // Batchmake uses two parameters to represent non-boolean // options. THe first of the parameters is the "flag", the // second is the value. THe Parent tag is used to ling flags // to values. wrapper << indent3 << "" << std::endl; // first parameter in the pair is ALWAYS a bool. If there is // not a pair, then the parameter is bool anyway. wrapper << indent4 << "1" << std::endl; // if we are going to be creating a paired set of parameters, // then name the first one the .flag and the // second one just for the value. if ((*pit).GetTag() != "boolean") { wrapper << indent4 << ""; wrapper << (*pit).GetName() + ".flag"; wrapper << "" << std::endl; } else { // just use the name wrapper << indent4 << ""; wrapper << (*pit).GetName(); wrapper << "" << std::endl; } // Value is the flag wrapper << indent4 << ""; wrapper << prefix + flag; wrapper << "" << std::endl; // The flag itself never has a parent wrapper << indent4 << "0" << std::endl; // BatchMake external flag is: // 0=nothing, 1=input, 2=output // // THe flag itself is always external = 0 wrapper << indent4 << "0" << std::endl; // Any module parameter that has a flag is optional. wrapper << indent4 << "1" << std::endl; wrapper << indent3 << "" << std::endl; // Is a child BatchMake parameter needed for the parameter? if ((*pit).GetTag() != "boolean") { pcount++; wrapper << indent3 << "" << std::endl; // find the module parameter type in the map to BatchMake types mp2bmIt = mp2bm.find((*pit).GetTag()); if (mp2bmIt != mp2bm.end()) { wrapper << indent4 << ""; wrapper << (*mp2bmIt).second; wrapper << "" << std::endl; } else { // unsupported type. map to string wrapper << indent4 << "4" << std::endl; } // THe name of the BatchMake paired parameter is just the // original parameter name wrapper << indent4 << ""; wrapper << (*pit).GetName(); wrapper << "" << std::endl; wrapper << indent4 << ""; wrapper << (*pit).GetDefault(); wrapper << "" << std::endl; // The parent is the previous parameter (the parameter for // the flag) wrapper << indent4 << "" << pcount - 1 << "" << std::endl; // BatchMake external flag is: // 0=nothing, 1=input, 2=output if ((*pit).GetTag() == "image" || (*pit).GetTag() == "geometry" || (*pit).GetTag() == "file") { if ((*pit).GetChannel() == "input") { wrapper << indent4 << "1" << std::endl; } else if ((*pit).GetChannel() == "output") { wrapper << indent4 << "2" << std::endl; } else { wrapper << indent4 << "0" << std::endl; } } else { wrapper << indent4 << "0" << std::endl; } // If the flag was specified, then the parameter for the // value cannot be option wrapper << indent4 << "0" << std::endl; wrapper << indent3 << "" << std::endl; } } } } // now tack on any parameters that are based on indices // // build a list of indices to traverse in order std::map indexmap; for (pgit = pgbeginit; pgit != pgendit; ++pgit) { // iterate over each parameter in this group std::vector::const_iterator pbeginit = (*pgit).GetParameters().begin(); std::vector::const_iterator pendit = (*pgit).GetParameters().end(); std::vector::const_iterator pit; for (pit = pbeginit; pit != pendit; ++pit) { if ((*pit).GetIndex() != "") { indexmap[atoi((*pit).GetIndex().c_str())] = (*pit); } } } // walk the index parameters in order std::map::const_iterator iit; for (iit = indexmap.begin(); iit != indexmap.end(); ++iit) { wrapper << indent3 << "" << std::endl; // find the module parameter type in the map to BatchMake types mp2bmIt = mp2bm.find((*iit).second.GetTag()); if (mp2bmIt != mp2bm.end()) { wrapper << indent4 << ""; wrapper << (*mp2bmIt).second; wrapper << "" << std::endl; } else { // unsupported type. map to string wrapper << indent4 << "4" << std::endl;; } wrapper << indent4 << ""; wrapper << (*iit).second.GetName(); wrapper << "" << std::endl; wrapper << indent4 << ""; wrapper << (*iit).second.GetDefault(); wrapper << "" << std::endl; // index parameters have no parents wrapper << indent4 << "0" << std::endl; // BatchMake external flag is: // 0=nothing, 1=input, 2=output if ((*iit).second.GetTag() == "image" || (*iit).second.GetTag() == "geometry" || (*iit).second.GetTag() == "file") { if ((*iit).second.GetChannel() == "input") { wrapper << indent4 << "1" << std::endl; } else if ((*iit).second.GetChannel() == "output") { wrapper << indent4 << "2" << std::endl; } else { wrapper << indent4 << "0" << std::endl; } } else { wrapper << indent4 << "0" << std::endl; } // Any index parameter is not optional wrapper << indent4 << "0" << std::endl; wrapper << indent3 << "" << std::endl; } wrapper << indent2 << "" << std::endl; wrapper << indent1 << "" << std::endl; wrapper << "" << std::endl; return wrapper.str(); }