|
12 | 12 |
|
13 | 13 | #include <functional>
|
14 | 14 | #include <list>
|
| 15 | +#include <map> |
| 16 | +#include <sstream> |
| 17 | +#include <string> |
15 | 18 |
|
16 | 19 | #if defined(__linux) || defined(__linux__)
|
17 | 20 | #pragma GCC diagnostic push
|
@@ -1117,6 +1120,149 @@ std::string writeTreeNodesModelXML(const BehaviorTreeFactory& factory,
|
1117 | 1120 | return std::string(printer.CStr(), size_t(printer.CStrSize() - 1));
|
1118 | 1121 | }
|
1119 | 1122 |
|
| 1123 | +std::string writeTreeDTD(const BehaviorTreeFactory& factory) |
| 1124 | +{ |
| 1125 | + /* Prepare the data. */ |
| 1126 | + std::map<std::string, const TreeNodeManifest*> ordered_models; |
| 1127 | + std::ostringstream models_max_one; |
| 1128 | + std::size_t i = 0; |
| 1129 | + for (const auto& [registration_id, model] : factory.manifests()) |
| 1130 | + { |
| 1131 | + ordered_models.insert({registration_id, &model}); |
| 1132 | + models_max_one << registration_id; |
| 1133 | + if (i != factory.manifests().size() - 1) |
| 1134 | + { |
| 1135 | + models_max_one << "|"; |
| 1136 | + } |
| 1137 | + i++; |
| 1138 | + } |
| 1139 | + |
| 1140 | + /* For a TreeNodesModel entry. */ |
| 1141 | + // PortsList ports; |
| 1142 | + // std::string description; |
| 1143 | + auto tree_nodes_model_dtd = [&models_max_one] (const TreeNodeManifest* manifest) -> std::string { |
| 1144 | + std::ostringstream dtd; |
| 1145 | + if ((manifest->type == NodeType::CONDITION) or (manifest->type == NodeType::ACTION)) |
| 1146 | + { |
| 1147 | + /* No children. */ |
| 1148 | + dtd << "<!ELEMENT " << manifest->registration_ID << " EMPTY>\n"; |
| 1149 | + } |
| 1150 | + else if ((manifest->type == NodeType::DECORATOR) |
| 1151 | + or (manifest->type == NodeType::SUBTREE)) |
| 1152 | + { |
| 1153 | + /* One child. */ |
| 1154 | + dtd << "<!ELEMENT " << manifest->registration_ID << " (" << models_max_one.str() << ")>\n"; |
| 1155 | + } |
| 1156 | + else |
| 1157 | + { |
| 1158 | + /* NodeType::CONTROL. */ |
| 1159 | + // TODO: check the code, the doc says 1..N but why not 0..N? |
| 1160 | + dtd << "<!ELEMENT " << manifest->registration_ID << " (" << models_max_one.str() << ")*>\n"; |
| 1161 | + } |
| 1162 | + dtd << "<!ATTLIST " << manifest->registration_ID << " name CDATA #IMPLIED>\n"; |
| 1163 | + for (const auto& [port_name, port_info] : manifest->ports) |
| 1164 | + { |
| 1165 | + std::string type; |
| 1166 | + if (port_info.type() == typeid(std::string)) |
| 1167 | + { |
| 1168 | + type = "CDATA"; |
| 1169 | + } |
| 1170 | + else if (port_info.type() == typeid(int)) |
| 1171 | + { |
| 1172 | + type = "CDATA"; |
| 1173 | + } |
| 1174 | + else if (port_info.type() == typeid(double)) |
| 1175 | + { |
| 1176 | + type = "CDATA"; |
| 1177 | + } |
| 1178 | + else if (port_info.type() == typeid(bool)) |
| 1179 | + { |
| 1180 | + type = "(true|false)"; |
| 1181 | + } |
| 1182 | + else |
| 1183 | + { |
| 1184 | + type = "CDATA"; |
| 1185 | + } |
| 1186 | + std::string attr_def; |
| 1187 | + if (port_info.defaultValue().empty()) |
| 1188 | + { |
| 1189 | + attr_def = "#REQUIRED"; |
| 1190 | + } |
| 1191 | + else |
| 1192 | + { |
| 1193 | + attr_def = "\"" + port_info.defaultValueString() + "\""; |
| 1194 | + } |
| 1195 | + dtd << "<!ATTLIST " << manifest->registration_ID << " " << port_name << " " << type << " " << attr_def << ">\n"; |
| 1196 | + } |
| 1197 | + return dtd.str(); |
| 1198 | + }; |
| 1199 | + |
| 1200 | + std::ostringstream dtd; |
| 1201 | + |
| 1202 | + dtd << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; |
| 1203 | + |
| 1204 | + // dtd << "<!DOCTYPE root [\n"; |
| 1205 | + dtd << "<!ELEMENT root (BehaviorTree|TreeNodesModel|include)*>\n"; |
| 1206 | + dtd << "<!ATTLIST root BTCPP_format CDATA #REQUIRED>\n"; |
| 1207 | + dtd << "<!ATTLIST root main_tree_to_execute CDATA #IMPLIED>\n"; |
| 1208 | + dtd << "\n"; |
| 1209 | + |
| 1210 | + dtd << "<!ELEMENT BehaviorTree (Action|Condition|Control|Decorator|SubTree|" << models_max_one.str() << ")>\n"; |
| 1211 | + dtd << "<!ATTLIST BehaviorTree ID CDATA #REQUIRED>\n"; |
| 1212 | + dtd << "\n"; |
| 1213 | + |
| 1214 | + dtd << "<!ELEMENT TreeNodesModel (Action|Condition|Control|Decorator|include)*>\n"; |
| 1215 | + dtd << "\n"; |
| 1216 | + |
| 1217 | + dtd << "<!ELEMENT include EMPTY>\n"; |
| 1218 | + dtd << "<!ATTLIST include path CDATA #REQUIRED>\n"; |
| 1219 | + dtd << "<!ATTLIST include ros_pkg CDATA #IMPLIED>\n"; |
| 1220 | + |
| 1221 | + dtd << "<!ELEMENT Action (input_port*,output_port*,description?)>\n"; |
| 1222 | + dtd << "<!ATTLIST Action ID CDATA #REQUIRED>\n"; |
| 1223 | + dtd << "\n"; |
| 1224 | + |
| 1225 | + dtd << "<!ELEMENT Condition (input_port*,description?)*>\n"; |
| 1226 | + dtd << "<!ATTLIST Condition ID CDATA #REQUIRED>\n"; |
| 1227 | + dtd << "\n"; |
| 1228 | + |
| 1229 | + dtd << "<!ELEMENT Control (input_port*,output_port*,description?)*>\n"; |
| 1230 | + dtd << "<!ATTLIST Control ID CDATA #REQUIRED>\n"; |
| 1231 | + dtd << "\n"; |
| 1232 | + |
| 1233 | + dtd << "<!ELEMENT Decorator (input_port*,output_port*,description?)*>\n"; |
| 1234 | + dtd << "<!ATTLIST Decorator ID CDATA #REQUIRED>\n"; |
| 1235 | + dtd << "\n"; |
| 1236 | + |
| 1237 | + dtd << "<!ELEMENT SubTree (#PCDATA)>\n"; |
| 1238 | + dtd << "<!ATTLIST SubTree ID CDATA #REQUIRED>\n"; |
| 1239 | + dtd << "\n"; |
| 1240 | + |
| 1241 | + dtd << "<!ELEMENT description (#PCDATA)>\n"; |
| 1242 | + dtd << "\n"; |
| 1243 | + |
| 1244 | + dtd << "<!ELEMENT input_port (#PCDATA)>\n"; |
| 1245 | + dtd << "<!ATTLIST input_port name CDATA #REQUIRED\n"; |
| 1246 | + dtd << " type CDATA #IMPLIED\n"; |
| 1247 | + dtd << " default CDATA #IMPLIED>\n"; |
| 1248 | + dtd << "\n"; |
| 1249 | + |
| 1250 | + dtd << "<!ELEMENT output_port (#PCDATA)>\n"; |
| 1251 | + dtd << "<!ATTLIST output_port name CDATA #REQUIRED\n"; |
| 1252 | + dtd << " type CDATA #REQUIRED>\n"; |
| 1253 | + dtd << "\n"; |
| 1254 | + |
| 1255 | + for (const auto& [registration_id, model] : ordered_models) |
| 1256 | + { |
| 1257 | + dtd << tree_nodes_model_dtd(model); |
| 1258 | + dtd << "\n"; |
| 1259 | + } |
| 1260 | + |
| 1261 | + // dtd << "]>\n"; |
| 1262 | + |
| 1263 | + return dtd.str(); |
| 1264 | +} |
| 1265 | + |
1120 | 1266 | Tree buildTreeFromText(const BehaviorTreeFactory& factory, const std::string& text,
|
1121 | 1267 | const Blackboard::Ptr& blackboard)
|
1122 | 1268 | {
|
|
0 commit comments