File indexing completed on 2025-01-18 10:17:37
0001
0002 #include "JInspector.h"
0003 #include <JANA/JEventSource.h>
0004 #include <stack>
0005 #include <JANA/Utils/JTablePrinter.h>
0006
0007
0008 JInspector::JInspector(const JEvent* event) : m_event(event) {}
0009
0010 void JInspector::Reset() {
0011 m_indexes_built = false;
0012 m_factories.clear();
0013 m_factory_index.clear();
0014 m_discrepancies.clear();
0015 }
0016
0017 void JInspector::SetDiscrepancies(std::set<std::string>&& diverging_factory_keys) {
0018 m_discrepancies = std::move(diverging_factory_keys);
0019 }
0020
0021 void JInspector::BuildIndices() {
0022 if (m_indexes_built) return;
0023 for (auto fac: m_event->GetFactorySet()->GetAllFactories()) {
0024 m_factories.push_back(fac);
0025 }
0026 std::sort(m_factories.begin(), m_factories.end(), [](const JFactory* first, const JFactory* second){
0027 return std::make_pair(first->GetObjectName(), first->GetTag()) <
0028 std::make_pair(second->GetObjectName(), second->GetTag());});
0029
0030 int i = 0;
0031 for (auto fac : m_factories) {
0032 std::string key = MakeFactoryKey(fac->GetObjectName(), fac->GetTag());
0033 std::pair<int, const JFactory*> value = {i++, fac};
0034 m_factory_index.insert({key, value});
0035 m_factory_index.insert({std::to_string(i), value});
0036 }
0037 m_indexes_built = true;
0038 }
0039
0040 std::vector<const JObject*> JInspector::FindAllAncestors(const JObject* root) {
0041 std::vector<const JObject*> all_ancestors;
0042 std::stack<const JObject*> to_visit;
0043 to_visit.push(root);
0044 while (!to_visit.empty()) {
0045 auto current_obj = to_visit.top();
0046 to_visit.pop();
0047 all_ancestors.push_back(current_obj);
0048 std::vector<const JObject*> current_ancestors;
0049 current_obj->GetT<JObject>(current_ancestors);
0050 for (auto obj : current_ancestors) {
0051 to_visit.push(obj);
0052 }
0053 }
0054 return all_ancestors;
0055 }
0056
0057 std::tuple<JFactory*, size_t, size_t> JInspector::LocateObject(const JEvent& event, const JObject* obj) {
0058 auto objName = obj->className();
0059 size_t fac_idx = 0;
0060 for (auto fac : event.GetAllFactories()) {
0061 if (fac->GetObjectName() == objName) {
0062 size_t obj_idx = 0;
0063 for (auto o : fac->GetAs<JObject>()) {
0064 if (obj == o) {
0065 return std::make_tuple(fac, fac_idx, obj_idx);
0066 }
0067 obj_idx++;
0068 }
0069 }
0070 fac_idx++;
0071 }
0072 return std::make_tuple(nullptr, -1, -1);
0073 }
0074
0075 void JInspector::PrintEvent() {
0076 ToText(m_event, m_format==Format::Json, m_out);
0077 }
0078 void JInspector::PrintFactories(int filter_level=0) {
0079 BuildIndices();
0080 ToText(m_factories, m_discrepancies, filter_level, m_format==Format::Json, m_out);
0081 }
0082
0083 void JInspector::PrintObjects(std::string factory_key) {
0084 BuildIndices();
0085 auto result = m_factory_index.find(factory_key);
0086 if (result == m_factory_index.end()) {
0087 m_out << "(Error: Invalid factory name or index)\n";
0088 return;
0089 }
0090 auto fac = const_cast<JFactory*>(result->second.second);
0091 auto objs = fac->GetAs<JObject>();
0092 ToText(objs, m_format==Format::Json, m_out);
0093 }
0094
0095 void JInspector::PrintFactoryDetails(std::string fac_key) {
0096 BuildIndices();
0097 auto result = m_factory_index.find(fac_key);
0098 if (result == m_factory_index.end()) {
0099 m_out << "(Error: Invalid factory name or index)\n";
0100 return;
0101 }
0102 auto fac = result->second.second;
0103 ToText(fac, m_format==Format::Json, m_out);
0104 }
0105
0106 void JInspector::PrintObject(std::string fac_key, int object_idx) {
0107 BuildIndices();
0108 auto result = m_factory_index.find(fac_key);
0109 if (result == m_factory_index.end()) {
0110 m_out << "(Error: Invalid factory name or index)\n";
0111 return;
0112 }
0113 JFactory* fac = const_cast<JFactory*>(result->second.second);
0114 auto objs = fac->GetAs<JObject>();
0115 if ((size_t) object_idx >= objs.size()) {
0116 m_out << "(Error: Object index out of range)" << std::endl;
0117 return;
0118 }
0119 auto obj = objs[object_idx];
0120 ToText(obj, m_format==Format::Json, m_out);
0121 }
0122 std::string JInspector::MakeFactoryKey(std::string name, std::string tag) {
0123 std::ostringstream ss;
0124 ss << name;
0125 if (!tag.empty()) {
0126 ss << ":" << tag;
0127 }
0128 return ss.str();
0129 }
0130
0131 void JInspector::PrintHelp() {
0132 m_out << " -----------------------------------------" << std::endl;
0133 m_out << " Available commands" << std::endl;
0134 m_out << " -----------------------------------------" << std::endl;
0135 m_out << " pe PrintEvent" << std::endl;
0136 m_out << " pf PrintFactories [filter_level <- {0,1,2,3}]" << std::endl;
0137 m_out << " pfd PrintFactoryDetails fac_idx" << std::endl;
0138 m_out << " po PrintObjects fac_idx" << std::endl;
0139 m_out << " po PrintObject fac_idx obj_idx" << std::endl;
0140 m_out << " pfp PrintFactoryParents fac_idx" << std::endl;
0141 m_out << " pop PrintObjectParents fac_idx obj_idx" << std::endl;
0142 m_out << " poa PrintObjectAncestors fac_idx obj_idx" << std::endl;
0143 m_out << " vt ViewAsTable" << std::endl;
0144 m_out << " vj ViewAsJson" << std::endl;
0145 m_out << " x Exit" << std::endl;
0146 m_out << " h Help" << std::endl;
0147 m_out << " -----------------------------------------" << std::endl;
0148 }
0149 void JInspector::ToText(const JEvent* event, bool asJson, std::ostream& out) {
0150 auto className = event->GetJEventSource()->GetTypeName();
0151 if (className.empty()) className = "(unknown)";
0152 if (asJson) {
0153 out << "{ \"run_number\": " << event->GetRunNumber();
0154 out << ", \"event_number\": " << event->GetEventNumber();
0155 out << ", \"source\": \"" << event->GetJEventSource()->GetResourceName();
0156 out << "\", \"class_name\": \"" << className;
0157 out << "\", \"is_sequential\": \"" << event->GetSequential() << "\"}";
0158 out << std::endl;
0159 }
0160 else {
0161 out << "Run number: " << event->GetRunNumber() << std::endl;
0162 out << "Event number: " << event->GetEventNumber() << std::endl;
0163 out << "Event source: " << event->GetJEventSource()->GetResourceName() << std::endl;
0164 out << "Class name: " << className << std::endl;
0165 out << "Sequential: " << event->GetSequential() << std::endl;
0166 }
0167 }
0168
0169 void JInspector::ToText(const JFactory* fac, bool asJson, std::ostream& out) {
0170
0171 auto pluginName = fac->GetPluginName();
0172 if (pluginName.empty()) pluginName = "(no plugin)";
0173
0174 auto factoryName = fac->GetFactoryName();
0175
0176
0177 auto tag = fac->GetTag();
0178 if (tag.empty()) tag = "(no tag)";
0179
0180 std::string creationStatus;
0181 switch (fac->GetCreationStatus()) {
0182 case JFactory::CreationStatus::NotCreatedYet: creationStatus = "NotCreatedYet"; break;
0183 case JFactory::CreationStatus::Created: creationStatus = "Created"; break;
0184 case JFactory::CreationStatus::Inserted: creationStatus = "Inserted"; break;
0185 case JFactory::CreationStatus::InsertedViaGetObjects: creationStatus = "InsertedViaGetObjects"; break;
0186 case JFactory::CreationStatus::NeverCreated: creationStatus = "NeverCreated"; break;
0187 default: creationStatus = "Unknown";
0188 }
0189
0190 if (!asJson) {
0191 out << "Plugin name " << pluginName << std::endl;
0192
0193 out << "Object name " << fac->GetObjectName() << std::endl;
0194 out << "Tag " << tag << std::endl;
0195 out << "Creation status " << creationStatus << std::endl;
0196 out << "Object count " << fac->GetNumObjects() << std::endl;
0197 out << "Persistent flag " << fac->TestFactoryFlag(JFactory::PERSISTENT) << std::endl;
0198 out << "NotObjectOwner flag " << fac->TestFactoryFlag(JFactory::NOT_OBJECT_OWNER) << std::endl;
0199 }
0200 else {
0201 out << "{" << std::endl;
0202 out << " \"plugin_name\": \"" << pluginName << "\"," << std::endl;
0203 out << " \"factory_name\": \"" << factoryName << "\"," << std::endl;
0204 out << " \"object_name\": \"" << fac->GetObjectName() << "\"," << std::endl;
0205 out << " \"tag\": \"" << tag << "\"," << std::endl;
0206 out << " \"creation\": \"" << creationStatus << "\"," << std::endl;
0207 out << " \"object_count\": " << fac->GetNumObjects() << "," << std::endl;
0208 out << " \"persistent\": " << fac->TestFactoryFlag(JFactory::PERSISTENT) << "," << std::endl;
0209 out << " \"not_obj_owner\": " << fac->TestFactoryFlag(JFactory::NOT_OBJECT_OWNER) << std::endl;
0210 out << "}" << std::endl;
0211 }
0212 }
0213
0214 void JInspector::ToText(const std::vector<JFactory*>& factories, const std::set<std::string>& discrepancies, int filterlevel, bool asJson, std::ostream &out) {
0215 size_t idx = -1;
0216 if (!asJson) {
0217 JTablePrinter t;
0218 t.AddColumn("Index", JTablePrinter::Justify::Right);
0219 t.AddColumn("Object");
0220 t.AddColumn("Tag");
0221 t.AddColumn("Creation status");
0222 t.AddColumn("Object count", JTablePrinter::Justify::Right);
0223 t.AddColumn("Discrepancy", JTablePrinter::Justify::Right);
0224 for (auto fac : factories) {
0225 auto tag = fac->GetTag();
0226 if (tag.empty()) tag = "(no tag)";
0227 std::string creationStatus;
0228 switch (fac->GetCreationStatus()) {
0229 case JFactory::CreationStatus::NotCreatedYet: creationStatus = "NotCreatedYet"; break;
0230 case JFactory::CreationStatus::Created: creationStatus = "Created"; break;
0231 case JFactory::CreationStatus::Inserted: creationStatus = "Inserted"; break;
0232 case JFactory::CreationStatus::InsertedViaGetObjects: creationStatus = "InsertedViaGetObjects"; break;
0233 case JFactory::CreationStatus::NeverCreated: creationStatus = "NeverCreated"; break;
0234 default: creationStatus = "Unknown";
0235 }
0236 idx += 1;
0237 if (filterlevel > 0 && (fac->GetCreationStatus()==JFactory::CreationStatus::NeverCreated ||
0238 fac->GetCreationStatus()==JFactory::CreationStatus::NotCreatedYet)) continue;
0239 if (filterlevel > 1 && (fac->GetNumObjects()== 0)) continue;
0240 if (filterlevel > 2 && (fac->GetCreationStatus()==JFactory::CreationStatus::Inserted ||
0241 fac->GetCreationStatus()==JFactory::CreationStatus::InsertedViaGetObjects)) continue;
0242
0243 char discrepancy = ' ';
0244 auto key = MakeFactoryKey(fac->GetObjectName(), fac->GetTag());
0245 if (discrepancies.find(key) != discrepancies.end()) discrepancy = 'x';
0246
0247 t | idx | fac->GetObjectName() | tag | creationStatus | fac->GetNumObjects() | discrepancy;
0248 }
0249 t.Render(out);
0250 }
0251 else {
0252 out << "{" << std::endl;
0253 for (auto fac : factories) {
0254 auto facName = fac->GetFactoryName();
0255 if (facName.empty()) facName = "null";
0256 auto tag = fac->GetTag();
0257 if (tag.empty()) tag = "null";
0258 out << " " << idx++ << ": { \"factory_name\": ";
0259 if (fac->GetFactoryName().empty()) {
0260 out << "null, ";
0261 }
0262 else {
0263 out << "\"" << fac->GetFactoryName() << "\", ";
0264 }
0265 out << "\"object_name\": \"" << fac->GetObjectName() << "\", \"tag\": ";
0266 if (fac->GetTag().empty()) {
0267 out << "null, ";
0268 }
0269 else {
0270 out << "\"" << fac->GetTag() << "\", ";
0271 }
0272 out << "\"object_count\": " << fac->GetNumObjects();
0273 out << "}," << std::endl;
0274 }
0275 out << "}" << std::endl;
0276 }
0277 }
0278
0279 void JInspector::ToText(std::vector<JObject*> objs, bool as_json, std::ostream& out) {
0280
0281 if (objs.empty()) {
0282 out << "(No objects found)" << std::endl;
0283 return;
0284 }
0285 std::set<std::string> objnames;
0286 for (auto obj: objs) {
0287 objnames.insert(obj->className());
0288 }
0289 if (objnames.size() == 1) {
0290 out << *(objnames.begin()) << std::endl;
0291 }
0292 else {
0293 out << "{ ";
0294 for (auto name : objnames) {
0295 out << name << ",";
0296 }
0297 out << "}" << std::endl;
0298 }
0299 if (as_json) {
0300 out << "{" << std::endl;
0301 for (size_t i = 0; i < objs.size(); ++i) {
0302 auto obj = objs[i];
0303 JObjectSummary summary;
0304 obj->Summarize(summary);
0305 out << " " << i << ": {";
0306 for (auto& field : summary.get_fields()) {
0307 out << "\"" << field.name << "\": \"" << field.value << "\", ";
0308 }
0309 out << "}" << std::endl;
0310 }
0311 out << "}" << std::endl;
0312 }
0313 else {
0314 JTablePrinter t;
0315 std::set<std::string> fieldnames_seen;
0316 std::vector<std::string> fieldnames_in_order;
0317 for (auto obj : objs) {
0318 JObjectSummary summary;
0319 obj->Summarize(summary);
0320 for (auto field : summary.get_fields()) {
0321 if (fieldnames_seen.find(field.name) == fieldnames_seen.end()) {
0322 fieldnames_in_order.push_back(field.name);
0323 fieldnames_seen.insert(field.name);
0324 }
0325 }
0326 }
0327 t.AddColumn("Index");
0328 for (auto fieldname : fieldnames_in_order) {
0329 t.AddColumn(fieldname);
0330 }
0331 for (size_t i = 0; i < objs.size(); ++i) {
0332 auto obj = objs[i];
0333 t | i;
0334 std::map<std::string, std::string> summary_map;
0335 JObjectSummary summary;
0336 obj->Summarize(summary);
0337 for (auto& field : summary.get_fields()) {
0338 summary_map[field.name] = field.value;
0339 }
0340 for (auto& fieldname : fieldnames_in_order) {
0341 auto result = summary_map.find(fieldname);
0342 if (result == summary_map.end()) {
0343 t | "(missing)";
0344 }
0345 else {
0346 t | result->second;
0347 }
0348 }
0349 }
0350 t.Render(out);
0351 }
0352 }
0353
0354 void JInspector::ToText(const JObject* obj, bool asJson, std::ostream& out) {
0355 out << obj->className() << std::endl;
0356 JObjectSummary summary;
0357 obj->Summarize(summary);
0358 if (asJson) {
0359 out << "[" << std::endl;
0360 for (auto& field : summary.get_fields()) {
0361 out << " { \"name\": \"" << field.name << "\", ";
0362 out << "\"value\": \"" << field.value << "\", ";
0363 out << "\"description\": \"" << field.description << "\" }" << std::endl;
0364 }
0365 out << "]" << std::endl;
0366 }
0367 else {
0368 JTablePrinter t;
0369 t.AddColumn("Field name");
0370 t.AddColumn("Value");
0371 t.AddColumn("Description");
0372 for (auto& field : summary.get_fields()) {
0373 t | field.name | field.value | field.description;
0374 }
0375 t.Render(out);
0376 }
0377 }
0378
0379 void JInspector::PrintFactoryParents(std::string factory_idx) {
0380
0381 bool callgraph_on = m_event->GetJCallGraphRecorder()->IsEnabled();
0382 if (!callgraph_on) {
0383 m_out << "(Error: Callgraph recording is currently disabled)" << std::endl;
0384 }
0385
0386 BuildIndices();
0387 auto result = m_factory_index.find(factory_idx);
0388 if (result == m_factory_index.end()) {
0389 m_out << "(Error: Invalid factory name or index)\n";
0390 return;
0391 }
0392 auto fac = result->second.second;
0393 auto obj_name = fac->GetObjectName();
0394 auto fac_tag = fac->GetTag();
0395 if (fac_tag.empty()) {
0396 m_out << obj_name << std::endl;
0397 }
0398 else {
0399 m_out << obj_name << ":" << fac_tag << std::endl;
0400 }
0401
0402 if (m_format != Format::Json) {
0403 JTablePrinter t;
0404 t.AddColumn("Index", JTablePrinter::Justify::Right);
0405 t.AddColumn("Object name");
0406 t.AddColumn("Tag");
0407 auto callgraph = m_event->GetJCallGraphRecorder()->GetCallGraph();
0408 bool found_anything = false;
0409 for (const auto& node : callgraph) {
0410 if ((node.caller_name == obj_name) && (node.caller_tag == fac_tag)) {
0411 found_anything = true;
0412 auto idx = m_factory_index[MakeFactoryKey(node.callee_name, node.callee_tag)].first;
0413 auto tag = node.callee_tag;
0414 if (tag.empty()) tag = "(no tag)";
0415 t | idx | node.callee_name | tag;
0416 }
0417 }
0418 if (!found_anything) {
0419 m_out << "(No parents found)" << std::endl;
0420 return;
0421 }
0422 t.Render(m_out);
0423 }
0424 else {
0425 auto callgraph = m_event->GetJCallGraphRecorder()->GetCallGraph();
0426 bool found_anything = false;
0427 m_out << "[" << std::endl;
0428 for (const auto& node : callgraph) {
0429 if ((node.caller_name == obj_name) && (node.caller_tag == fac_tag)) {
0430 found_anything = true;
0431 auto idx = m_factory_index[MakeFactoryKey(node.callee_name, node.callee_tag)].first;
0432 auto tag = node.callee_tag;
0433 m_out << " { \"index\": " << idx << ", \"object_name\": \"" << node.callee_name << "\", \"tag\": ";
0434 if (tag.empty()) {
0435 m_out << "null }," << std::endl;
0436 }
0437 else {
0438 m_out << "\"" << tag << "\" }," << std::endl;
0439 }
0440 }
0441 }
0442 m_out << "]" << std::endl;
0443 if (!found_anything) {
0444 m_out << "(No ancestors found)" << std::endl;
0445 return;
0446 }
0447 }
0448 }
0449
0450 void JInspector::PrintObjectParents(std::string factory_key, int object_idx) {
0451
0452 BuildIndices();
0453 auto result = m_factory_index.find(factory_key);
0454 if (result == m_factory_index.end()) {
0455 m_out << "(Error: Invalid factory name or index)\n";
0456 return;
0457 }
0458 auto fac = const_cast<JFactory*>(result->second.second);
0459 auto objs = fac->GetAs<JObject>();
0460 if ((size_t) object_idx >= objs.size()) {
0461 m_out << "(Error: Object index out of range)" << std::endl;
0462 return;
0463 }
0464 auto obj = objs[object_idx];
0465 m_out << obj->className() << std::endl;
0466 std::vector<const JObject*> parents;
0467 obj->GetT<JObject>(parents);
0468 if (parents.empty()) {
0469 m_out << "(No parents found)" << std::endl;
0470 return;
0471 }
0472
0473 if (m_format == Format::Table) {
0474 JTablePrinter t;
0475 t.AddColumn("Object name");
0476 t.AddColumn("Tag");
0477 t.AddColumn("Factory Index", JTablePrinter::Justify::Right);
0478 t.AddColumn("Object Index", JTablePrinter::Justify::Right);
0479 t.AddColumn("Object contents");
0480 for (auto parent : parents) {
0481 JFactory* fac;
0482 size_t fac_idx;
0483 size_t obj_idx;
0484 std::tie(fac, fac_idx, obj_idx) = LocateObject(*m_event, parent);
0485 if (fac == nullptr) {
0486 m_out << "(Error: Unable to find factory containing object with classname '" << obj->className() << "')" << std::endl;
0487 continue;
0488 }
0489 JObjectSummary summary;
0490 parent->Summarize(summary);
0491
0492 auto tag = fac->GetTag();
0493 if (tag.empty()) tag = "(no tag)";
0494 std::ostringstream objval;
0495 objval << "{";
0496 for (auto& field : summary.get_fields()) {
0497 objval << field.name << ": " << field.value << ", ";
0498 }
0499 objval << "}";
0500
0501 t | fac->GetObjectName() | tag | fac_idx | obj_idx | objval.str();
0502 }
0503 t.Render(m_out);
0504 }
0505 else {
0506 m_out << "[" << std::endl;
0507 for (auto ancestor : FindAllAncestors(obj)) {
0508 JFactory* fac;
0509 size_t fac_idx;
0510 size_t obj_idx;
0511 std::tie(fac, fac_idx, obj_idx) = LocateObject(*m_event, ancestor);
0512 if (fac == nullptr) {
0513 m_out << "(Error: Unable to find factory containing object with classname '" << obj->className() << "')" << std::endl;
0514 continue;
0515 }
0516 auto tag = fac->GetTag();
0517 if (tag.empty()) tag = "(no tag)";
0518
0519 m_out << " " << "{ " << std::endl << " \"object_name\": \"" << fac->GetObjectName() << "\", ";
0520 if (tag.empty()) {
0521 m_out << "\"tag\": null, ";
0522 }
0523 else {
0524 m_out << "\"tag\": \"" << tag << "\", ";
0525 }
0526 m_out << "\"fac_index\": " << fac_idx << ", \"obj_index\": " << obj_idx << "," << std::endl;
0527 m_out << " \"object_contents\": ";
0528
0529 JObjectSummary summary;
0530 ancestor->Summarize(summary);
0531 m_out << "{";
0532 for (auto& field : summary.get_fields()) {
0533 m_out << "\"" << field.name << "\": \"" << field.value << "\", ";
0534 }
0535 m_out << "}" << std::endl;
0536 m_out << " }, " << std::endl;
0537 }
0538 m_out << "]" << std::endl;
0539 }
0540 }
0541
0542 void JInspector::PrintObjectAncestors(std::string factory_idx, int object_idx) {
0543
0544 BuildIndices();
0545 auto result = m_factory_index.find(factory_idx);
0546 if (result == m_factory_index.end()) {
0547 m_out << "(Error: Invalid factory name or index)\n";
0548 return;
0549 }
0550 auto fac = const_cast<JFactory*>(result->second.second);
0551 auto objs = fac->GetAs<JObject>();
0552 if ((size_t) object_idx >= objs.size()) {
0553 m_out << "(Error: Object index out of range)" << std::endl;
0554 return;
0555 }
0556 auto obj = objs[object_idx];
0557 m_out << obj->className() << std::endl;
0558 auto ancestors = FindAllAncestors(obj);
0559 if (ancestors.empty()) {
0560 m_out << "(No ancestors found)" << std::endl;
0561 return;
0562 }
0563
0564 if (m_format == Format::Table) {
0565 JTablePrinter t;
0566 t.AddColumn("Object name");
0567 t.AddColumn("Tag");
0568 t.AddColumn("Factory index", JTablePrinter::Justify::Right);
0569 t.AddColumn("Object index", JTablePrinter::Justify::Right);
0570 t.AddColumn("Object contents");
0571 for (auto ancestor : FindAllAncestors(obj)) {
0572 JFactory* fac;
0573 size_t fac_idx, obj_idx;
0574 std::tie(fac, fac_idx, obj_idx) = LocateObject(*m_event, ancestor);
0575 if (fac == nullptr) {
0576 m_out << "(Error: Unable to find factory containing object with classname '" << obj->className() << "')" << std::endl;
0577 continue;
0578 }
0579 JObjectSummary summary;
0580 ancestor->Summarize(summary);
0581
0582 auto tag = fac->GetTag();
0583 if (tag.empty()) tag = "(no tag)";
0584 std::ostringstream objval;
0585 objval << "{";
0586 for (auto& field : summary.get_fields()) {
0587 objval << field.name << ": " << field.value << ", ";
0588 }
0589 objval << "}";
0590
0591 t | fac->GetObjectName() | tag | fac_idx | obj_idx | objval.str();
0592 }
0593 t.Render(m_out);
0594 }
0595 else {
0596 m_out << "[" << std::endl;
0597 for (auto ancestor : FindAllAncestors(obj)) {
0598 JFactory* fac;
0599 size_t fac_idx, obj_idx;
0600 std::tie(fac, fac_idx, obj_idx) = LocateObject(*m_event, ancestor);
0601 if (fac == nullptr) {
0602 m_out << "(Error: Unable to find factory containing object with classname '" << obj->className() << "')" << std::endl;
0603 continue;
0604 }
0605 auto tag = fac->GetTag();
0606 if (tag.empty()) tag = "(no tag)";
0607
0608 m_out << " " << "{ " << std::endl << " \"object_name\": \"" << fac->GetObjectName() << "\", ";
0609 if (tag.empty()) {
0610 m_out << "\"tag\": null, ";
0611 }
0612 else {
0613 m_out << "\"tag\": \"" << tag << "\", ";
0614 }
0615 m_out << "\"fac_index\": " << fac_idx << ", \"obj_index\": " << obj_idx << "," << std::endl;
0616 m_out << " \"object_contents\": ";
0617
0618 JObjectSummary summary;
0619 ancestor->Summarize(summary);
0620 m_out << "{";
0621 for (auto& field : summary.get_fields()) {
0622 m_out << "\"" << field.name << "\": \"" << field.value << "\", ";
0623 }
0624 m_out << "}" << std::endl;
0625 m_out << " }, " << std::endl;
0626 }
0627 m_out << "]" << std::endl;
0628 }
0629 }
0630
0631 void JInspector::Loop() {
0632 bool stay_in_loop = true;
0633 auto app = m_event->GetJApplication();
0634 m_enable_timeout_on_exit = app->IsTimeoutEnabled();
0635 m_enable_ticker_on_exit = app->IsTickerEnabled();
0636 m_event->GetJApplication()->SetTicker( false );
0637 m_event->GetJApplication()->SetTimeoutEnabled( false );
0638 m_out << std::endl;
0639 m_out << "--------------------------------------------------------------------------------------" << std::endl;
0640 m_out << "Welcome to JANA's interactive inspector! Type `Help` or `h` to see available commands." << std::endl;
0641 m_out << "--------------------------------------------------------------------------------------" << std::endl;
0642 PrintEvent();
0643 while (stay_in_loop) {
0644 std::string user_input;
0645 m_out << std::endl << "JANA: "; m_out.flush();
0646
0647 std::getline(m_in, user_input);
0648
0649 std::stringstream ss(user_input);
0650 std::string token;
0651 ss >> token;
0652 std::vector<std::string> args;
0653 std::string arg;
0654 while (ss >> arg) {
0655 args.push_back(arg);
0656 }
0657 try {
0658 if (token == "PrintEvent" || token == "pe") {
0659 PrintEvent();
0660 }
0661 else if ((token == "PrintFactories" || token == "pf") && args.empty()) {
0662 PrintFactories(0);
0663 }
0664 else if ((token == "PrintFactories" || token == "pf") && args.size() == 1) {
0665 PrintFactories(std::stoi(args[0]));
0666 }
0667 else if ((token == "PrintFactoryDetails" || token == "pfd") && (args.size() == 1)) {
0668 PrintFactoryDetails(args[0]);
0669 }
0670 else if ((token == "PrintObjects" || token == "po") && (args.size() == 1)) {
0671 PrintObjects(args[0]);
0672 }
0673 else if ((token == "PrintObject" || token == "po") && (args.size() == 2)) {
0674 PrintObject(args[0], std::stoi(args[1]));
0675 }
0676 else if ((token == "PrintFactoryParents" || token == "pfp") && (args.size() == 1)) {
0677 PrintFactoryParents(args[0]);
0678 }
0679 else if ((token == "PrintObjectParents" || token == "pop") && (args.size() == 2)) {
0680 PrintObjectParents(args[0], std::stoi(args[1]));
0681 }
0682 else if ((token == "PrintObjectAncestors" || token == "poa") && (args.size() == 2)) {
0683 PrintObjectAncestors(args[0], std::stoi(args[1]));
0684 }
0685 else if (token == "ViewAsTable" || token == "vt") {
0686 m_format = Format::Table;
0687 m_out << "(Switching to table view mode)" << std::endl;
0688 }
0689 else if (token == "ViewAsJson" || token == "vj") {
0690 m_format = Format::Json;
0691 m_out << "(Switching to JSON view mode)" << std::endl;
0692 }
0693 else if (token == "Continue" || token == "c") {
0694 stay_in_loop = false;
0695 }
0696 else if (token == "Exit" || token == "x") {
0697 stay_in_loop = false;
0698 }
0699 else if (token == "Help" || token == "h") {
0700 PrintHelp();
0701 }
0702 else if (token == "") {
0703
0704 }
0705 else {
0706 m_out << "(Error: Unrecognized command, or wrong argument count)" << std::endl;
0707 PrintHelp();
0708 }
0709
0710 }
0711 catch (JException& ex) {
0712 m_out << "(JException: Maybe you tried to print out objects that are not JObjects)" << std::endl;
0713 }
0714 catch (std::invalid_argument&) {
0715 m_out << "(Parse error: Maybe an argument needs to be an int)" << std::endl;
0716 }
0717 catch (...) {
0718 m_out << "(Unknown error)" << std::endl;
0719 }
0720 }
0721
0722 if (m_enable_ticker_on_exit) {
0723 m_event->GetJApplication()->SetTicker( true );
0724 }
0725 if (m_enable_timeout_on_exit) {
0726 m_event->GetJApplication()->SetTimeoutEnabled( true );
0727 }
0728 }