1 #include "otsdaq-core/ConfigurationInterface/ConfigurationTree.h"
5 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
6 #include "otsdaq-core/Macros/StringMacros.h"
7 #include "otsdaq-core/TableCore/TableBase.h"
12 #define __MF_SUBJECT__ "ConfigurationTree"
14 const std::string ConfigurationTree::DISCONNECTED_VALUE =
"X";
15 const std::string ConfigurationTree::VALUE_TYPE_DISCONNECTED =
"Disconnected";
16 const std::string ConfigurationTree::VALUE_TYPE_NODE =
"Node";
19 ConfigurationTree::ConfigurationTree()
23 , linkParentConfig_(0)
28 , disconnectedTargetName_(
"")
29 , disconnectedLinkID_(
"")
65 const std::string& groupId,
67 const std::string& linkColName,
68 const std::string& linkColValue,
69 const unsigned int linkBackRow,
70 const unsigned int linkBackCol,
71 const std::string& disconnectedTargetName,
72 const std::string& disconnectedLinkID,
73 const std::string& childLinkIndex,
74 const unsigned int row,
75 const unsigned int col)
76 : configMgr_(configMgr)
79 , linkParentConfig_(linkParentConfig)
80 , linkColName_(linkColName)
81 , linkColValue_(linkColValue)
82 , linkBackRow_(linkBackRow)
83 , linkBackCol_(linkBackCol)
84 , disconnectedTargetName_(disconnectedTargetName)
85 , disconnectedLinkID_(disconnectedLinkID)
86 , childLinkIndex_(childLinkIndex)
96 __SS__ <<
"Invalid empty pointer given to tree!\n"
97 <<
"\n\tconfigMgr_=" << configMgr_ <<
"\n\tconfiguration_=" << table_
98 <<
"\n\tconfigView_=" << tableView_ << __E__;
100 ss << nodeDump() << __E__;
105 tableView_ = &(table_->getView());
108 if(tableView_ && tableView_->getColumnInfo(tableView_->getColUID()).getType() !=
109 TableViewColumnInfo::TYPE_UID)
111 __SS__ <<
"Missing UID column (must column of type "
112 << TableViewColumnInfo::TYPE_UID
113 <<
") in config view : " << tableView_->getTableName() << __E__;
115 ss << nodeDump() << __E__;
122 ConfigurationTree::~ConfigurationTree(
void)
133 void ConfigurationTree::print(
const unsigned int& depth, std::ostream& out)
const
135 recursivePrint(*
this, depth, out,
"\t");
145 out << space << t.getValueName() <<
" :\t" << t.getValueAsString() << __E__;
150 out << space << t.getValueName();
151 if(t.isDisconnected())
153 out <<
" :\t" << t.getValueAsString() << __E__;
156 out <<
" (" << (t.isGroupLinkNode() ?
"Group" :
"U")
157 <<
"ID=" << t.getValueAsString() <<
") : " << __E__;
160 out << space << t.getValueAsString() <<
" : " << __E__;
166 auto C = t.getChildren();
168 out << space <<
"{" << __E__;
170 recursivePrint(c.second, depth - 1, out, space +
" ");
172 out << space <<
"}" << __E__;
178 std::string ConfigurationTree::handleValidateValueForColumn(
186 __SS__ <<
"Null configView" << __E__;
188 ss << nodeDump() << __E__;
191 __COUT__ <<
"handleValidateValueForColumn<string>" << __E__;
192 return configView->validateValueForColumn(value, col);
200 void ConfigurationTree::getValue(std::string& value)
const
204 if(row_ != TableView::INVALID &&
205 col_ != TableView::INVALID)
212 __COUT__ <<
"Success following path to tree node!" << __E__;
220 value = tableView_->validateValueForColumn(valueAsTreeNode.getValueAsString(),
223 __COUT__ <<
"Successful value!" << __E__;
237 tableView_->getValue(value, row_, col_);
239 else if(row_ == TableView::INVALID &&
240 col_ == TableView::INVALID)
242 if(isLinkNode() && isDisconnected())
244 (groupId_ ==
"") ? getValueName() : groupId_;
248 value = (groupId_ ==
"") ? table_->getTableName() : groupId_;
250 else if(row_ == TableView::INVALID)
252 __SS__ <<
"Malformed ConfigurationTree" << __E__;
255 else if(col_ == TableView::INVALID)
256 tableView_->getValue(value, row_, tableView_->getColUID());
259 __SS__ <<
"Impossible." << __E__;
277 std::string ConfigurationTree::getValue()
const
280 ConfigurationTree::getValue(value);
293 if(row_ != TableView::INVALID &&
294 col_ != TableView::INVALID)
296 std::string bitmapString;
297 tableView_->getValue(bitmapString, row_, col_);
299 __COUTV__(bitmapString);
300 if(bitmapString == TableViewColumnInfo::DATATYPE_STRING_DEFAULT)
302 bitmap.isDefault_ =
true;
306 bitmap.isDefault_ =
false;
310 bitmap.bitmap_.clear();
312 bool openRow =
false;
313 unsigned int startInt = -1;
314 for(
unsigned int i = 0; i < bitmapString.length(); i++)
316 __COUTV__(bitmapString[i]);
324 if(bitmapString[i] ==
'[')
328 bitmap.bitmap_.push_back(std::vector<uint64_t>());
330 else if(bitmapString[i] ==
']')
334 else if(bitmapString[i] ==
',')
338 <<
"Too many ']' or ',' characters in bit map configuration"
341 ss << nodeDump() << __E__;
345 else if(startInt == (
unsigned int)-1)
347 if(bitmapString[i] ==
']')
352 else if(bitmapString[i] >=
'0' &&
353 bitmapString[i] <=
'9')
357 else if(bitmapString[i] ==
',')
359 __SS__ <<
"Too many ',' characters in bit map configuration"
362 ss << nodeDump() << __E__;
370 if(bitmapString[i] ==
374 bitmap.bitmap_[row].push_back(strtoul(
375 bitmapString.substr(startInt, i - startInt).c_str(), 0, 0));
378 else if(bitmapString[i] ==
',')
380 bitmap.bitmap_[row].push_back(strtoul(
381 bitmapString.substr(startInt, i - startInt).c_str(), 0, 0));
387 for(
unsigned int r = 0; r < bitmap.bitmap_.size(); ++r)
389 for(
unsigned int c = 0; c < bitmap.bitmap_[r].size(); ++c)
391 __COUT__ << r <<
"," << c <<
" = " << bitmap.bitmap_[r][c] << __E__;
393 __COUT__ <<
"================" << __E__;
399 __SS__ <<
"Requesting getValue must be on a value node." << __E__;
401 ss << nodeDump() << __E__;
413 ConfigurationTree::getValueAsBitMap(value);
420 std::string ConfigurationTree::getEscapedValue()
const
422 if(row_ != TableView::INVALID &&
423 col_ != TableView::INVALID)
424 return tableView_->getEscapedValueAsString(row_, col_);
426 __SS__ <<
"Can not get escaped value except from a value node!"
427 <<
" This node is type '" << getNodeType() <<
"." << __E__;
429 ss << nodeDump() << __E__;
435 const std::string& ConfigurationTree::getTableName(
void)
const
439 __SS__ <<
"Can not get configuration name of node with no configuration pointer! "
440 <<
"Is there a broken link? " << __E__;
441 if(linkParentConfig_)
443 ss <<
"Error occurred traversing from " << linkParentConfig_->getTableName()
445 << linkParentConfig_->getView().getValueAsString(
446 linkBackRow_, linkParentConfig_->getView().getColUID())
447 <<
"' at row " << linkBackRow_ <<
" col '"
448 << linkParentConfig_->getView().getColumnInfo(linkBackCol_).getName()
451 ss << StringMacros::stackTrace() << __E__;
456 return table_->getTableName();
464 const std::string& ConfigurationTree::getFieldTableName(
void)
const
469 if(!linkParentConfig_)
471 __SS__ <<
"Can not get configuration name of link node field with no parent "
472 "configuration pointer!"
474 ss << nodeDump() << __E__;
477 return linkParentConfig_->getTableName();
480 return getTableName();
485 const std::string& ConfigurationTree::getDisconnectedTableName(
void)
const
487 if(isLinkNode() && isDisconnected())
488 return disconnectedTargetName_;
490 __SS__ <<
"Can not get disconnected target name of node unless it is a disconnected "
494 ss << nodeDump() << __E__;
500 const std::string& ConfigurationTree::getDisconnectedLinkID(
void)
const
502 if(isLinkNode() && isDisconnected())
503 return disconnectedLinkID_;
505 __SS__ <<
"Can not get disconnected target name of node unless it is a disconnected "
509 ss << nodeDump() << __E__;
515 const TableVersion& ConfigurationTree::getTableVersion(
void)
const
519 __SS__ <<
"Can not get configuration version of node with no config view pointer!"
522 ss << nodeDump() << __E__;
525 return tableView_->getVersion();
530 const time_t& ConfigurationTree::getTableCreationTime(
void)
const
534 __SS__ <<
"Can not get configuration creation time of node with no config view "
538 ss << nodeDump() << __E__;
541 return tableView_->getCreationTime();
548 std::vector<std::string> ConfigurationTree::getFixedChoices(
void)
const
550 if(getValueType() != TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA &&
551 getValueType() != TableViewColumnInfo::TYPE_BITMAP_DATA && !isLinkNode())
553 __SS__ <<
"Can not get fixed choices of node with value type of '"
554 << getValueType() <<
".' Node must be a link or a value node with type '"
555 << TableViewColumnInfo::TYPE_BITMAP_DATA <<
"' or '"
556 << TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA <<
".'" << __E__;
558 ss << nodeDump() << __E__;
562 std::vector<std::string> retVec;
566 if(!linkParentConfig_)
569 <<
"Can not get fixed choices of node with no parent config view pointer!"
572 ss << nodeDump() << __E__;
582 const TableView* parentView = &(linkParentConfig_->getView());
583 int c = parentView->findCol(linkColName_);
585 std::pair<
unsigned int ,
unsigned int > linkPair;
587 parentView->getChildLink(c, isGroupLink, linkPair);
590 std::vector<std::string> choices = parentView->getColumnInfo(c).getDataChoices();
591 for(
const auto& choice : choices)
592 retVec.push_back(choice);
599 __SS__ <<
"Can not get fixed choices of node with no config view pointer!"
602 ss << nodeDump() << __E__;
607 retVec.push_back(tableView_->getColumnInfo(col_).getDefaultValue());
608 std::vector<std::string> choices = tableView_->getColumnInfo(col_).getDataChoices();
609 for(
const auto& choice : choices)
610 retVec.push_back(choice);
623 const std::string& ConfigurationTree::getValueAsString(
bool returnLinkTableValue)
const
627 if(returnLinkTableValue)
628 return linkColValue_;
629 else if(isDisconnected())
630 return ConfigurationTree::DISCONNECTED_VALUE;
631 else if(row_ == TableView::INVALID &&
632 col_ == TableView::INVALID)
633 return (groupId_ ==
"") ? table_->getTableName() : groupId_;
634 else if(col_ == TableView::INVALID)
635 return tableView_->getDataView()[row_][tableView_->getColUID()];
638 __SS__ <<
"Impossible Link." << __E__;
640 ss << nodeDump() << __E__;
644 else if(row_ != TableView::INVALID &&
645 col_ != TableView::INVALID)
646 return tableView_->getDataView()[row_][col_];
647 else if(row_ == TableView::INVALID &&
648 col_ == TableView::INVALID)
649 return (groupId_ ==
"") ? table_->getTableName() : groupId_;
650 else if(row_ == TableView::INVALID)
652 __SS__ <<
"Malformed ConfigurationTree" << __E__;
654 ss << nodeDump() << __E__;
657 else if(col_ == TableView::INVALID)
658 return tableView_->getDataView()[row_][tableView_->getColUID()];
661 __SS__ <<
"Impossible." << __E__;
663 ss << nodeDump() << __E__;
672 const std::string& ConfigurationTree::getUIDAsString(
void)
const
674 if(isValueNode() || isUIDLinkNode())
675 return tableView_->getDataView()[row_][tableView_->getColUID()];
678 __SS__ <<
"Can not get UID of node with type '" << getNodeType()
679 <<
".' Node type must be '" << ConfigurationTree::NODE_TYPE_VALUE
680 <<
"' or '" << ConfigurationTree::NODE_TYPE_UID_LINK <<
".'" << __E__;
682 ss << nodeDump() << __E__;
690 const std::string& ConfigurationTree::getValueDataType(
void)
const
693 return tableView_->getColumnInfo(col_).getDataType();
695 return TableViewColumnInfo::DATATYPE_STRING;
701 bool ConfigurationTree::isDefaultValue(
void)
const
706 if(getValueDataType() == TableViewColumnInfo::DATATYPE_STRING)
708 if(getValueType() == TableViewColumnInfo::TYPE_ON_OFF ||
709 getValueType() == TableViewColumnInfo::TYPE_TRUE_FALSE ||
710 getValueType() == TableViewColumnInfo::TYPE_YES_NO)
711 return getValueAsString() ==
712 TableViewColumnInfo::DATATYPE_BOOL_DEFAULT;
714 else if(getValueType() == TableViewColumnInfo::TYPE_COMMENT)
715 return getValueAsString() == TableViewColumnInfo::DATATYPE_COMMENT_DEFAULT ||
716 getValueAsString() ==
719 return getValueAsString() == TableViewColumnInfo::DATATYPE_STRING_DEFAULT;
721 else if(getValueDataType() == TableViewColumnInfo::DATATYPE_NUMBER)
722 return getValueAsString() == TableViewColumnInfo::DATATYPE_NUMBER_DEFAULT;
723 else if(getValueDataType() == TableViewColumnInfo::DATATYPE_TIME)
724 return getValueAsString() == TableViewColumnInfo::DATATYPE_TIME_DEFAULT;
732 const std::string& ConfigurationTree::getValueType(
void)
const
735 return tableView_->getColumnInfo(col_).getType();
736 else if(isLinkNode() && isDisconnected())
737 return ConfigurationTree::VALUE_TYPE_DISCONNECTED;
739 return ConfigurationTree::VALUE_TYPE_NODE;
748 return tableView_->getColumnInfo(col_);
751 __SS__ <<
"Can only get column info from a value node! "
752 <<
"The node type is " << getNodeType() << __E__;
754 ss << nodeDump() << __E__;
761 const unsigned int& ConfigurationTree::getRow(
void)
const {
return row_; }
765 const unsigned int& ConfigurationTree::getColumn(
void)
const {
return col_; }
770 const unsigned int& ConfigurationTree::getFieldRow(
void)
const
784 const unsigned int& ConfigurationTree::getFieldColumn(
void)
const
797 const std::string& ConfigurationTree::getChildLinkIndex(
void)
const
801 __SS__ <<
"Can only get link ID from a link! "
802 <<
"The node type is " << getNodeType() << __E__;
804 ss << nodeDump() << __E__;
807 return childLinkIndex_;
813 const std::string& ConfigurationTree::getValueName(
void)
const
816 return tableView_->getColumnInfo(col_).getName();
817 else if(isLinkNode())
821 __SS__ <<
"Can only get value name of a value node!" << __E__;
823 ss << nodeDump() << __E__;
832 const std::string& childPath,
833 bool doNotThrowOnBrokenUIDLinks,
834 const std::string& originalNodeString)
838 if(childPath.length() <= 1)
840 return tree.recursiveGetNode(
841 childPath, doNotThrowOnBrokenUIDLinks, originalNodeString);
880 bool doNotThrowOnBrokenUIDLinks)
const
882 return recursiveGetNode(
883 nodeString, doNotThrowOnBrokenUIDLinks,
"" );
886 const std::string& nodeString,
887 bool doNotThrowOnBrokenUIDLinks,
888 const std::string& originalNodeString)
const
895 if(nodeString.length() < 1)
897 __SS__ <<
"Invalid empty node name! Looking for child node from node '"
898 << getValue() <<
"'..." << __E__;
900 ss << nodeDump() << __E__;
904 bool startingSlash = nodeString[0] ==
'/';
906 std::string nodeName = nodeString.substr(
907 startingSlash ? 1 : 0, nodeString.find(
'/', 1) - (startingSlash ? 1 : 0));
910 std::string childPath =
911 nodeString.substr(nodeName.length() + (startingSlash ? 1 : 0));
924 return recurse(configMgr_->getNode(nodeName),
926 doNotThrowOnBrokenUIDLinks,
929 else if(row_ == TableView::INVALID && col_ == TableView::INVALID)
935 __SS__ <<
"Missing configView pointer! Likely attempting to access a "
936 "child node through a disconnected link node."
939 ss << nodeDump() << __E__;
959 ? tableView_->findRow(tableView_->getColUID(), nodeName)
960 : tableView_->findRowInGroup(tableView_->getColUID(),
965 doNotThrowOnBrokenUIDLinks,
968 else if(row_ == TableView::INVALID)
970 __SS__ <<
"Malformed ConfigurationTree" << __E__;
972 ss << nodeDump() << __E__;
975 else if(col_ == TableView::INVALID)
991 __SS__ <<
"Missing configView pointer! Likely attempting to access a "
992 "child node through a disconnected link node."
995 ss << nodeDump() << __E__;
999 unsigned int c = tableView_->findCol(nodeName);
1000 std::pair<
unsigned int ,
unsigned int > linkPair;
1001 bool isGroupLink, isLink;
1002 if((isLink = tableView_->getChildLink(c, isGroupLink, linkPair)) &&
1013 childConfig = configMgr_->getTableByName(
1014 tableView_->getDataView()[row_][linkPair.first]);
1015 childConfig->getView();
1017 if(doNotThrowOnBrokenUIDLinks)
1019 childConfig->getView().findRow(
1020 childConfig->getView().getColUID(),
1021 tableView_->getDataView()[row_][linkPair.second]);
1040 tableView_->getDataView()[row_][c],
1045 tableView_->getDataView()[row_][linkPair.first],
1048 tableView_->getDataView()[row_][linkPair.second],
1051 tableView_->getColumnInfo(c).getChildLinkIndex());
1061 tableView_->getDataView()[row_][c],
1068 tableView_->getColumnInfo(c).getChildLinkIndex(),
1069 childConfig->getView().findRow(
1070 childConfig->getView().getColUID(),
1071 tableView_->getDataView()[row_][linkPair.second])),
1073 doNotThrowOnBrokenUIDLinks,
1074 originalNodeString);
1086 childConfig = configMgr_->getTableByName(
1087 tableView_->getDataView()[row_][linkPair.first]);
1088 childConfig->getView();
1092 if(tableView_->getDataView()[row_][linkPair.first] !=
1093 TableViewColumnInfo::DATATYPE_LINK_DEFAULT)
1095 <<
"Found disconnected node! Failed link target "
1097 << nodeName <<
" to table:id="
1098 << tableView_->getDataView()[row_][linkPair.first] <<
":"
1099 << tableView_->getDataView()[row_][linkPair.second] << __E__;
1105 tableView_->getDataView()[row_][linkPair.second],
1108 tableView_->getDataView()[row_][c],
1113 tableView_->getDataView()[row_][linkPair.first],
1116 tableView_->getDataView()[row_][linkPair.second],
1119 tableView_->getColumnInfo(c).getChildLinkIndex());
1127 ->getDataView()[row_][linkPair.second],
1130 tableView_->getDataView()[row_][c],
1137 tableView_->getColumnInfo(c).getChildLinkIndex()),
1139 doNotThrowOnBrokenUIDLinks,
1140 originalNodeString);
1152 TableView::INVALID ,
1153 TableView::INVALID ,
1162 catch(std::runtime_error& e)
1164 __SS__ <<
"\n\nError occurred descending from node '" << getValue()
1165 <<
"' in table '" << getTableName() <<
"' looking for child '" << nodeName
1168 ss <<
"The original node search string was '" << originalNodeString <<
".'"
1170 ss <<
"--- Additional error detail: \n\n" << e.what() << __E__;
1172 ss << nodeDump() << __E__;
1177 __SS__ <<
"\n\nError occurred descending from node '" << getValue()
1178 <<
"' in table '" << getTableName() <<
"' looking for child '" << nodeName
1181 ss <<
"The original node search string was '" << originalNodeString <<
".'"
1184 ss << nodeDump() << __E__;
1190 <<
"\n\nError occurred descending from node '" << getValue() <<
"' in table '"
1191 << getTableName() <<
"' looking for child '" << nodeName <<
"'\n\n"
1192 <<
"Invalid depth! getNode() called from a value point in the Configuration Tree."
1194 ss <<
"The original node search string was '" << originalNodeString <<
".'" << __E__;
1196 ss << nodeDump() << __E__;
1203 std::string ConfigurationTree::nodeDump(
void)
const
1205 __SS__ <<
"ConfigurationTree::nodeDump() "
1206 "=====================================\nConfigurationTree::nodeDump():"
1213 <<
"Error occurred from node '" << getValueAsString() <<
"'..." << __E__;
1221 <<
"Error occurred from node '" << getValue() <<
"' in table '"
1222 << getTableName() <<
".'" << __E__;
1229 auto children = getChildrenNames();
1231 <<
"Here is the list of possible children (count = " << children.size()
1233 for(
auto& child : children)
1234 ss <<
"\t\t" << child << __E__;
1237 ss <<
"\n\nHere is the culprit table printout:\n\n";
1238 tableView_->print(ss);
1247 ss <<
"\n\n" << StringMacros::stackTrace() << __E__;
1253 ss <<
"end ConfigurationTree::nodeDump() ====================================="
1261 unsigned int backSteps)
const
1263 for(
unsigned int i = 0; i < backSteps; i++)
1264 nodeName = nodeName.substr(0, nodeName.find_last_of(
'/'));
1266 return getNode(nodeName);
1271 unsigned int forwardSteps)
const
1276 while(s < nodeName.length() && nodeName[s] ==
'/')
1279 for(
unsigned int i = 0; i < forwardSteps; i++)
1280 s = nodeName.find(
'/', s) + 1;
1282 return getNode(nodeName.substr(0, s));
1288 bool ConfigurationTree::isValueNode(
void)
const
1290 return (row_ != TableView::INVALID && col_ != TableView::INVALID);
1296 bool ConfigurationTree::isValueBoolType(
void)
const
1298 return isValueNode() && tableView_->getColumnInfo(col_).isBoolType();
1304 bool ConfigurationTree::isValueNumberDataType(
void)
const
1306 return isValueNode() && tableView_->getColumnInfo(col_).isNumberDataType();
1314 bool ConfigurationTree::isDisconnected(
void)
const
1318 __SS__ <<
"\n\nError occurred testing link connection at node with value '"
1319 << getValue() <<
"' in table '" << getTableName() <<
"'\n\n"
1321 ss <<
"This is not a Link node! It is node type '" << getNodeType()
1322 <<
".' Only a Link node can be disconnected." << __E__;
1324 ss << nodeDump() << __E__;
1328 return !table_ || !tableView_;
1334 bool ConfigurationTree::isLinkNode(
void)
const {
return linkColName_ !=
""; }
1339 const std::string ConfigurationTree::NODE_TYPE_GROUP_TABLE =
"GroupTableNode";
1340 const std::string ConfigurationTree::NODE_TYPE_TABLE =
"TableNode";
1341 const std::string ConfigurationTree::NODE_TYPE_GROUP_LINK =
"GroupLinkNode";
1342 const std::string ConfigurationTree::NODE_TYPE_UID_LINK =
"UIDLinkNode";
1343 const std::string ConfigurationTree::NODE_TYPE_VALUE =
"ValueNode";
1344 const std::string ConfigurationTree::NODE_TYPE_UID =
"UIDNode";
1345 const std::string ConfigurationTree::NODE_TYPE_ROOT =
"RootNode";
1347 std::string ConfigurationTree::getNodeType(
void)
const
1350 return ConfigurationTree::NODE_TYPE_ROOT;
1351 if(isConfigurationNode() && groupId_ !=
"")
1352 return ConfigurationTree::NODE_TYPE_GROUP_TABLE;
1353 if(isConfigurationNode())
1354 return ConfigurationTree::NODE_TYPE_TABLE;
1355 if(isGroupLinkNode())
1356 return ConfigurationTree::NODE_TYPE_GROUP_LINK;
1358 return ConfigurationTree::NODE_TYPE_UID_LINK;
1360 return ConfigurationTree::NODE_TYPE_VALUE;
1361 return ConfigurationTree::NODE_TYPE_UID;
1367 bool ConfigurationTree::isGroupLinkNode(
void)
const
1369 return (isLinkNode() && groupId_ !=
"");
1375 bool ConfigurationTree::isUIDLinkNode(
void)
const
1377 return (isLinkNode() && groupId_ ==
"");
1383 bool ConfigurationTree::isUIDNode(
void)
const
1385 return (row_ != TableView::INVALID && col_ == TableView::INVALID);
1404 std::vector<ConfigurationTree::RecordField> ConfigurationTree::getCommonFields(
1405 const std::vector<std::string /*uid*/>& recordList,
1406 const std::vector<std::string /*relative-path*/>& fieldAcceptList,
1407 const std::vector<std::string /*relative-path*/>& fieldRejectList,
1409 bool autoSelectFilterFields)
const
1412 if(!isRootNode() && !isConfigurationNode())
1414 __SS__ <<
"Can only get getCommonFields from a root or table node! "
1415 <<
"The node type is " << getNodeType() << __E__;
1417 ss << nodeDump() << __E__;
1421 std::vector<ConfigurationTree::RecordField> fieldCandidateList;
1422 std::vector<int> fieldCount;
1465 for(
unsigned int i = 0; i < recordList.size(); ++i)
1469 auto recordChildren = getNode(recordList[i]).getChildren();
1470 for(
const auto& fieldNode : recordChildren)
1475 if(fieldNode.second.isValueNode() || fieldNode.second.isGroupLinkNode())
1478 if(fieldNode.second.isValueNode())
1480 if(fieldNode.second.getColumnInfo().getType() ==
1481 TableViewColumnInfo::TYPE_AUTHOR ||
1482 fieldNode.second.getColumnInfo().getType() ==
1483 TableViewColumnInfo::TYPE_TIMESTAMP)
1492 found = fieldAcceptList.size() ?
false
1494 for(
const auto& fieldFilter : fieldAcceptList)
1495 if(StringMacros::wildCardMatch(fieldFilter, fieldNode.first))
1506 for(
const auto& fieldFilter : fieldRejectList)
1507 if(StringMacros::wildCardMatch(fieldFilter, fieldNode.first))
1518 if(fieldNode.second.isGroupLinkNode())
1520 __COUT__ <<
"isGroupLinkNode " << fieldNode.first << __E__;
1524 std::pair<
unsigned int ,
1528 tableView_->getChildLink(tableView_->findCol(fieldNode.first),
1535 table_->getTableName(),
1537 tableView_->getColumnInfo(linkPair.first).getName(),
1539 &tableView_->getColumnInfo(linkPair.first)));
1540 fieldCount.push_back(-1);
1543 table_->getTableName(),
1545 tableView_->getColumnInfo(linkPair.second).getName(),
1547 &tableView_->getColumnInfo(linkPair.second)));
1548 fieldCount.push_back(-1);
1553 fieldNode.second.getTableName(),
1557 &fieldNode.second.getColumnInfo()));
1558 fieldCount.push_back(-1);
1565 else if(depth > 0 && fieldNode.second.isUIDLinkNode() &&
1566 !fieldNode.second.isDisconnected())
1569 fieldNode.second.recursiveGetCommonFields(
1575 fieldNode.first +
"/",
1587 for(
unsigned int i = 0; i < fieldCandidateList.size(); ++i)
1592 if(fieldCount[i] != -1 && fieldCount[i] != (
int)recordList.size())
1597 fieldCount.erase(fieldCount.begin() + i);
1598 fieldCandidateList.erase(fieldCandidateList.begin() + i);
1607 if(autoSelectFilterFields)
1611 std::set<std::pair<
unsigned int ,
unsigned int >>
1614 unsigned int highestPriority = 0;
1615 for(
unsigned int i = 0; i < fieldCandidateList.size(); ++i)
1623 if(fieldCandidateList[i].columnInfo_->isBoolType())
1624 prioritySet.emplace(
1625 std::make_pair(0 , i ));
1626 else if(fieldCandidateList[i].columnInfo_->isGroupID())
1628 prioritySet.emplace(
1629 std::make_pair(1 , i ));
1630 if(highestPriority < 1)
1631 highestPriority = 1;
1633 else if(fieldCandidateList[i].columnInfo_->getType() ==
1634 TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
1636 prioritySet.emplace(
1637 std::make_pair(3 , i ));
1638 if(highestPriority < 3)
1639 highestPriority = 3;
1641 else if(fieldCandidateList[i].columnInfo_->getType() ==
1642 TableViewColumnInfo::TYPE_DATA)
1644 prioritySet.emplace(
1645 std::make_pair(10 , i ));
1646 if(highestPriority < 10)
1647 highestPriority = 10;
1651 fieldCandidateList[i].tableName_ =
1658 __COUTV__(StringMacros::setToString(prioritySet));
1663 unsigned int cnt = 0;
1664 for(
const auto& priorityFieldIndex : prioritySet)
1674 fieldCandidateList[priorityFieldIndex.second].tableName_ =
1679 for(
unsigned int i = 0; i < fieldCandidateList.size(); ++i)
1681 if(fieldCandidateList[i].tableName_ ==
"")
1685 fieldCandidateList.erase(fieldCandidateList.begin() + i);
1691 for(
unsigned int i = 0; i < fieldCandidateList.size(); ++i)
1692 __COUT__ <<
"Final " << fieldCandidateList[i].relativePath_
1693 << fieldCandidateList[i].columnName_ << __E__;
1695 return fieldCandidateList;
1703 std::set<std::string > ConfigurationTree::getUniqueValuesForField(
1704 const std::vector<std::string /*relative-path*/>& recordList,
1705 const std::string& fieldName)
const
1708 if(!isConfigurationNode())
1710 __SS__ <<
"Can only get getCommonFields from a table node! "
1711 <<
"The node type is " << getNodeType() << __E__;
1713 ss << nodeDump() << __E__;
1717 std::set<std::string > uniqueValues;
1724 for(
unsigned int i = 0; i < recordList.size(); ++i)
1726 __COUT__ <<
"Checking " << recordList[i] << __E__;
1734 uniqueValues.emplace(
1735 getNode(recordList[i]).getNode(fieldName).getValueAsString(
true));
1738 return uniqueValues;
1744 void ConfigurationTree::recursiveGetCommonFields(
1745 std::vector<ConfigurationTree::RecordField>& fieldCandidateList,
1746 std::vector<int>& fieldCount,
1747 const std::vector<std::string /*relative-path*/>& fieldAcceptList,
1748 const std::vector<std::string /*relative-path*/>& fieldRejectList,
1750 const std::string& relativePathBase,
1751 bool inFirstRecord)
const
1775 auto tableName = getTableName();
1776 auto uid = getUIDAsString();
1779 auto recordChildren = getChildren();
1780 for(
const auto& fieldNode : recordChildren)
1782 if(fieldNode.second.isValueNode())
1785 if(fieldNode.second.getColumnInfo().getType() ==
1786 TableViewColumnInfo::TYPE_AUTHOR ||
1787 fieldNode.second.getColumnInfo().getType() ==
1788 TableViewColumnInfo::TYPE_TIMESTAMP)
1795 found = fieldAcceptList.size() ?
false :
true;
1797 for(
const auto& fieldFilter : fieldAcceptList)
1798 if(StringMacros::wildCardMatch(fieldFilter, fieldNode.first))
1809 for(
const auto& fieldFilter : fieldRejectList)
1810 if(StringMacros::wildCardMatch(fieldFilter, fieldNode.first))
1827 &fieldNode.second.getColumnInfo()));
1828 fieldCount.push_back(1);
1835 for(j = 0; j < fieldCandidateList.size(); ++j)
1837 if((relativePathBase + fieldNode.first) ==
1838 (fieldCandidateList[j].relativePath_ +
1839 fieldCandidateList[j].columnName_))
1850 else if(depth > 0 && fieldNode.second.isUIDLinkNode() &&
1851 !fieldNode.second.isDisconnected())
1855 fieldNode.second.recursiveGetCommonFields(
1861 (relativePathBase + fieldNode.first) +
"/",
1874 std::vector<std::vector<std::pair<std::string, ConfigurationTree>>>
1875 ConfigurationTree::getChildrenByPriority(
1876 std::map<std::string /*relative-path*/, std::string /*value*/> filterMap,
1877 bool onlyStatusTrue)
const
1879 std::vector<std::vector<std::pair<std::string, ConfigurationTree>>> retVector;
1883 bool filtering = filterMap.size();
1885 std::string fieldValue;
1887 bool createContainer;
1889 std::vector<std::vector<std::string>> childrenNamesByPriority =
1890 getChildrenNamesByPriority(onlyStatusTrue);
1892 for(
auto& childNamesAtPriority : childrenNamesByPriority)
1894 createContainer =
true;
1896 for(
auto& childName : childNamesAtPriority)
1906 for(
const auto& filterPair : filterMap)
1908 std::string filterPath = childName +
"/" + filterPair.first;
1909 __COUTV__(filterPath);
1913 std::vector<std::string> fieldValues;
1914 StringMacros::getVectorFromString(
1917 std::set<char>({
','}) );
1919 __COUTV__(fieldValues.size());
1923 for(
const auto& fieldValue : fieldValues)
1934 __COUT__ <<
"\t\tCheck: " << filterPair.first
1935 <<
" == " << fieldValue <<
" => "
1936 << StringMacros::decodeURIComponent(fieldValue)
1938 << this->getNode(filterPath).getValueAsString(
true)
1941 if(StringMacros::wildCardMatch(
1942 StringMacros::decodeURIComponent(fieldValue),
1943 this->getNode(filterPath).getValueAsString(
true)))
1953 __SS__ <<
"Failed to access filter path '" << filterPath
1954 <<
"' - aborting." << __E__;
1956 ss << nodeDump() << __E__;
1973 retVector.push_back(
1974 std::vector<std::pair<std::string, ConfigurationTree>>());
1975 createContainer =
false;
1978 retVector[retVector.size() - 1].push_back(
1979 std::pair<std::string, ConfigurationTree>(
1980 childName, this->getNode(childName,
true)));
1994 std::vector<std::pair<std::string, ConfigurationTree>> ConfigurationTree::getChildren(
1995 std::map<std::string /*relative-path*/, std::string /*value*/> filterMap,
1997 bool onlyStatusTrue)
const
1999 std::vector<std::pair<std::string, ConfigurationTree>> retVector;
2003 bool filtering = filterMap.size();
2005 std::string fieldValue;
2007 std::vector<std::string> childrenNames = getChildrenNames(byPriority, onlyStatusTrue);
2008 for(
auto& childName : childrenNames)
2018 for(
const auto& filterPair : filterMap)
2020 std::string filterPath = childName +
"/" + filterPair.first;
2021 __COUTV__(filterPath);
2025 std::vector<std::string> fieldValues;
2026 StringMacros::getVectorFromString(
2029 std::set<char>({
','}) );
2031 __COUTV__(fieldValues.size());
2035 for(
const auto& fieldValue : fieldValues)
2046 <<
"\t\tCheck: " << filterPair.first <<
" == " << fieldValue
2047 <<
" => " << StringMacros::decodeURIComponent(fieldValue)
2048 <<
" ??? " << this->getNode(filterPath).getValueAsString(
true)
2051 if(StringMacros::wildCardMatch(
2052 StringMacros::decodeURIComponent(fieldValue),
2053 this->getNode(filterPath).getValueAsString(
true)))
2063 __SS__ <<
"Failed to access filter path '" << filterPath
2064 <<
"' - aborting." << __E__;
2066 ss << nodeDump() << __E__;
2081 retVector.push_back(std::pair<std::string, ConfigurationTree>(
2082 childName, this->getNode(childName,
true)));
2092 std::map<std::string, ConfigurationTree> ConfigurationTree::getChildrenMap(
void)
const
2094 std::map<std::string, ConfigurationTree> retMap;
2098 std::vector<std::string> childrenNames = getChildrenNames();
2099 for(
auto& childName : childrenNames)
2102 retMap.insert(std::pair<std::string, ConfigurationTree>(
2103 childName, this->getNode(childName)));
2111 bool ConfigurationTree::isRootNode(
void)
const {
return (!table_); }
2114 bool ConfigurationTree::isConfigurationNode(
void)
const
2116 return (table_ && row_ == TableView::INVALID && col_ == TableView::INVALID);
2122 std::vector<std::vector<std::string>> ConfigurationTree::getChildrenNamesByPriority(
2123 bool onlyStatusTrue)
const
2125 std::vector<std::vector<std::string >> retVector;
2129 __SS__ <<
"Can not get children names of '" << getValueAsString()
2130 <<
"' with null configuration view pointer!" << __E__;
2131 if(isLinkNode() && isDisconnected())
2132 ss <<
" This node is a disconnected link to " << getDisconnectedTableName()
2135 ss << nodeDump() << __E__;
2139 if(row_ == TableView::INVALID && col_ == TableView::INVALID)
2150 std::map<uint64_t , std::vector<
unsigned int >>
2152 std::vector<std::string > retPrioritySet;
2154 unsigned int col = tableView_->getColPriority();
2156 uint64_t tmpPriority;
2158 for(
unsigned int r = 0; r < tableView_->getNumberOfRows(); ++r)
2159 if(groupId_ ==
"" ||
2160 tableView_->isEntryInGroup(r, childLinkIndex_, groupId_))
2165 tableView_->getValue(
2166 tmpStatus, r, tableView_->getColStatus());
2171 tableView_->getValue(tmpPriority, r, col);
2173 orderedByPriority[tmpPriority ? tmpPriority : 100].push_back(r);
2179 for(
const auto& priorityChildRowVector : orderedByPriority)
2181 retVector.push_back(std::vector<std::string /*child name*/>());
2182 for(
const auto& priorityChildRow : priorityChildRowVector.second)
2183 retVector[retVector.size() - 1].push_back(
2184 tableView_->getDataView()[priorityChildRow]
2185 [tableView_->getColUID()]);
2188 __COUT__ <<
"Returning priority children list." << __E__;
2191 catch(std::runtime_error& e)
2193 __COUT_WARN__ <<
"Error identifying priority. Assuming all children have "
2194 "equal priority (Error: "
2195 << e.what() << __E__;
2201 for(
unsigned int r = 0; r < tableView_->getNumberOfRows(); ++r)
2202 if(groupId_ ==
"" || tableView_->isEntryInGroup(r, childLinkIndex_, groupId_))
2207 tableView_->getValue(tmpStatus, r, tableView_->getColStatus());
2212 retVector.push_back(std::vector<std::string /*child name*/>());
2213 retVector[retVector.size() - 1].push_back(
2214 tableView_->getDataView()[r][tableView_->getColUID()]);
2217 else if(row_ == TableView::INVALID)
2219 __SS__ <<
"Malformed ConfigurationTree" << __E__;
2221 ss << nodeDump() << __E__;
2224 else if(col_ == TableView::INVALID)
2229 for(
unsigned int c = 0; c < tableView_->getNumberOfColumns(); ++c)
2230 if(c == tableView_->getColUID() ||
2232 tableView_->getColumnInfo(c).isChildLinkGroupID() ||
2233 tableView_->getColumnInfo(c).isChildLinkUID())
2237 retVector.push_back(std::vector<std::string /*child name*/>());
2238 retVector[retVector.size() - 1].push_back(
2239 tableView_->getColumnInfo(c).getName());
2245 __SS__ <<
"\n\nError occurred looking for children of nodeName=" << getValueName()
2247 <<
"Invalid depth! getChildrenValues() called from a value point in the "
2248 "Configuration Tree."
2251 ss << nodeDump() << __E__;
2261 std::vector<std::string> ConfigurationTree::getChildrenNames(
bool byPriority,
2262 bool onlyStatusTrue)
const
2264 std::vector<std::string > retVector;
2268 __SS__ <<
"Can not get children names of '" << getValueAsString()
2269 <<
"' with null configuration view pointer!" << __E__;
2270 if(isLinkNode() && isDisconnected())
2271 ss <<
" This node is a disconnected link to " << getDisconnectedTableName()
2276 if(row_ == TableView::INVALID && col_ == TableView::INVALID)
2287 std::map<uint64_t , std::vector<
unsigned int >>
2289 std::vector<std::string > retPrioritySet;
2291 unsigned int col = tableView_->getColPriority();
2293 uint64_t tmpPriority;
2295 for(
unsigned int r = 0; r < tableView_->getNumberOfRows(); ++r)
2296 if(groupId_ ==
"" ||
2297 tableView_->isEntryInGroup(r, childLinkIndex_, groupId_))
2302 tableView_->getValue(
2303 tmpStatus, r, tableView_->getColStatus());
2309 tableView_->getValue(tmpPriority, r, col);
2311 orderedByPriority[tmpPriority ? tmpPriority : 100].push_back(r);
2317 for(
const auto& priorityChildRowVector : orderedByPriority)
2318 for(
const auto& priorityChildRow : priorityChildRowVector.second)
2319 retVector.push_back(
2320 tableView_->getDataView()[priorityChildRow]
2321 [tableView_->getColUID()]);
2323 __COUT__ <<
"Returning priority children list." << __E__;
2326 catch(std::runtime_error& e)
2328 __COUT_WARN__ <<
"Priority configuration not found. Assuming all "
2329 "children have equal priority (Error: "
2330 << e.what() << __E__;
2336 for(
unsigned int r = 0; r < tableView_->getNumberOfRows(); ++r)
2337 if(groupId_ ==
"" || tableView_->isEntryInGroup(r, childLinkIndex_, groupId_))
2342 tableView_->getValue(tmpStatus, r, tableView_->getColStatus());
2348 retVector.push_back(
2349 tableView_->getDataView()[r][tableView_->getColUID()]);
2352 else if(row_ == TableView::INVALID)
2354 __SS__ <<
"Malformed ConfigurationTree" << __E__;
2356 ss << nodeDump() << __E__;
2359 else if(col_ == TableView::INVALID)
2364 for(
unsigned int c = 0; c < tableView_->getNumberOfColumns(); ++c)
2365 if(c == tableView_->getColUID() ||
2367 tableView_->getColumnInfo(c).isChildLinkGroupID() ||
2368 tableView_->getColumnInfo(c).isChildLinkUID())
2371 retVector.push_back(tableView_->getColumnInfo(c).getName());
2376 __SS__ <<
"\n\nError occurred looking for children of nodeName=" << getValueName()
2378 <<
"Invalid depth! getChildrenValues() called from a value point in the "
2379 "Configuration Tree."
2382 ss << nodeDump() << __E__;
2400 __SS__ <<
"Invalid node for get value." << __E__;
2404 std::string valueString =
2405 tableView_->getValueAsString(row_, col_,
true );
2407 if(valueString.size() && valueString[0] ==
'/')
2414 __COUT__ <<
"Found a valid tree path in value!" << __E__;
2419 __SS__ <<
"Invalid tree path." << __E__;
2425 __SS__ <<
"Invalid value string '" << valueString
2426 <<
"' - must start with a '/' character." << __E__;