1 #include "otsdaq/ConfigurationInterface/ConfigurationTree.h"
5 #include "otsdaq/ConfigurationInterface/ConfigurationManager.h"
6 #include "otsdaq/Macros/StringMacros.h"
7 #include "otsdaq/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";
17 const std::string ConfigurationTree::ROOT_NAME =
"/";
20 ConfigurationTree::ConfigurationTree()
24 , linkParentConfig_(0)
29 , disconnectedTargetName_(
"")
30 , 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_ <<
"\n\tconfigView_=" << tableView_ << __E__;
99 ss << nodeDump() << __E__;
104 tableView_ = &(table_->getView());
107 if(tableView_ && tableView_->getColumnInfo(tableView_->getColUID()).getType() != TableViewColumnInfo::TYPE_UID)
109 __SS__ <<
"Missing UID column (must column of type " << TableViewColumnInfo::TYPE_UID <<
") in config view : " << tableView_->getTableName() << __E__;
111 ss << nodeDump() << __E__;
118 ConfigurationTree::~ConfigurationTree(
void)
129 void ConfigurationTree::print(
const unsigned int& depth, std::ostream& out)
const { recursivePrint(*
this, depth, out,
"\t"); }
132 void ConfigurationTree::recursivePrint(
const ConfigurationTree& t,
unsigned int depth, std::ostream& out, std::string space)
135 out << space << t.getValueName() <<
" :\t" << t.getValueAsString() << __E__;
140 out << space << t.getValueName();
141 if(t.isDisconnected())
143 out <<
" :\t" << t.getValueAsString() << __E__;
146 out <<
" (" << (t.isGroupLinkNode() ?
"Group" :
"U") <<
"ID=" << t.getValueAsString() <<
") : " << __E__;
149 out << space << t.getValueAsString() <<
" : " << __E__;
155 auto C = t.getChildren();
157 out << space <<
"{" << __E__;
159 recursivePrint(c.second, depth - 1, out, space +
" ");
161 out << space <<
"}" << __E__;
171 __SS__ <<
"Null configView" << __E__;
173 ss << nodeDump() << __E__;
176 __COUT__ <<
"handleValidateValueForColumn<string>" << __E__;
177 return configView->validateValueForColumn(value, col);
185 void ConfigurationTree::getValue(std::string& value)
const
189 if(row_ != TableView::INVALID && col_ != TableView::INVALID)
196 __COUT__ <<
"Success following path to tree node!" << __E__;
204 value = tableView_->validateValueForColumn(valueAsTreeNode.getValueAsString(), col_);
206 __COUT__ <<
"Successful value!" << __E__;
220 tableView_->getValue(value, row_, col_);
222 else if(row_ == TableView::INVALID && col_ == TableView::INVALID)
224 if(isLinkNode() && isDisconnected())
225 value = (groupId_ ==
"") ? getValueName() : groupId_;
229 value = (groupId_ ==
"") ? table_->getTableName() : groupId_;
231 else if(row_ == TableView::INVALID)
233 __SS__ <<
"Malformed ConfigurationTree" << __E__;
236 else if(col_ == TableView::INVALID)
237 tableView_->getValue(value, row_, tableView_->getColUID());
240 __SS__ <<
"Impossible." << __E__;
258 std::string ConfigurationTree::getValue()
const
261 ConfigurationTree::getValue(value);
277 std::string ConfigurationTree::getValueWithDefault(
const std::string& defaultValue)
const
282 return ConfigurationTree::getValue();
294 if(row_ != TableView::INVALID && 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] ==
',')
337 __SS__ <<
"Too many ']' or ',' characters in bit map configuration" << __E__;
339 ss << nodeDump() << __E__;
343 else if(startInt == (
unsigned int)-1)
345 if(bitmapString[i] ==
']')
350 else if(bitmapString[i] >=
'0' && bitmapString[i] <=
'9')
354 else if(bitmapString[i] ==
',')
356 __SS__ <<
"Too many ',' characters in bit map configuration" << __E__;
358 ss << nodeDump() << __E__;
366 if(bitmapString[i] ==
']')
369 bitmap.bitmap_[row].push_back(strtoul(bitmapString.substr(startInt, i - startInt).c_str(), 0, 0));
372 else if(bitmapString[i] ==
',')
374 bitmap.bitmap_[row].push_back(strtoul(bitmapString.substr(startInt, i - startInt).c_str(), 0, 0));
380 for(
unsigned int r = 0; r < bitmap.bitmap_.size(); ++r)
382 for(
unsigned int c = 0; c < bitmap.bitmap_[r].size(); ++c)
384 __COUT__ << r <<
"," << c <<
" = " << bitmap.bitmap_[r][c] << __E__;
386 __COUT__ <<
"================" << __E__;
392 __SS__ <<
"Requesting getValue must be on a value node." << __E__;
394 ss << nodeDump() << __E__;
406 ConfigurationTree::getValueAsBitMap(value);
413 std::string ConfigurationTree::getEscapedValue()
const
415 if(row_ != TableView::INVALID && col_ != TableView::INVALID)
416 return tableView_->getEscapedValueAsString(row_, col_);
418 __SS__ <<
"Can not get escaped value except from a value node!"
419 <<
" This node is type '" << getNodeType() <<
"." << __E__;
421 ss << nodeDump() << __E__;
427 const std::string& ConfigurationTree::getTableName(
void)
const
431 __SS__ <<
"Can not get configuration name of node with no configuration pointer! "
432 <<
"Is there a broken link? " << __E__;
433 if(linkParentConfig_)
435 ss <<
"Error occurred traversing from " << linkParentConfig_->getTableName() <<
" UID '"
436 << linkParentConfig_->getView().getValueAsString(linkBackRow_, linkParentConfig_->getView().getColUID()) <<
"' at row " << linkBackRow_
437 <<
" col '" << linkParentConfig_->getView().getColumnInfo(linkBackCol_).getName() <<
".'" << __E__;
439 ss << StringMacros::stackTrace() << __E__;
444 return table_->getTableName();
449 const unsigned int& ConfigurationTree::getNodeRow(
void)
const
451 if(isUIDNode() || isValueNode())
454 __SS__ <<
"Can only get row from a UID or value node!" << __E__;
455 if(linkParentConfig_)
457 ss <<
"Error occurred traversing from " << linkParentConfig_->getTableName() <<
" UID '"
458 << linkParentConfig_->getView().getValueAsString(linkBackRow_, linkParentConfig_->getView().getColUID()) <<
"' at row " << linkBackRow_ <<
" col '"
459 << linkParentConfig_->getView().getColumnInfo(linkBackCol_).getName() <<
".'" << __E__;
461 ss << StringMacros::stackTrace() << __E__;
473 const std::string& ConfigurationTree::getFieldTableName(
void)
const
478 if(!linkParentConfig_)
480 __SS__ <<
"Can not get configuration name of link node field with no parent "
481 "configuration pointer!"
483 ss << nodeDump() << __E__;
486 return linkParentConfig_->getTableName();
489 return getTableName();
494 const std::string& ConfigurationTree::getDisconnectedTableName(
void)
const
496 if(isLinkNode() && isDisconnected())
497 return disconnectedTargetName_;
499 __SS__ <<
"Can not get disconnected target name of node unless it is a disconnected "
503 ss << nodeDump() << __E__;
509 const std::string& ConfigurationTree::getDisconnectedLinkID(
void)
const
511 if(isLinkNode() && isDisconnected())
512 return disconnectedLinkID_;
514 __SS__ <<
"Can not get disconnected target name of node unless it is a disconnected "
518 ss << nodeDump() << __E__;
524 const TableVersion& ConfigurationTree::getTableVersion(
void)
const
528 __SS__ <<
"Can not get configuration version of node with no config view pointer!" << __E__;
530 ss << nodeDump() << __E__;
533 return tableView_->getVersion();
538 const time_t& ConfigurationTree::getTableCreationTime(
void)
const
542 __SS__ <<
"Can not get configuration creation time of node with no config view "
546 ss << nodeDump() << __E__;
549 return tableView_->getCreationTime();
555 std::set<std::string> ConfigurationTree::getSetOfGroupIDs(
void)
const
559 __SS__ <<
"Can not get set of group IDs of node with value type of '" << getNodeType() <<
".' Node must be a GroupID node." << __E__;
561 ss << nodeDump() << __E__;
565 return tableView_->getSetOfGroupIDs(col_, row_);
573 std::vector<std::string> ConfigurationTree::getFixedChoices(
void)
const
575 if(getValueType() != TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA && getValueType() != TableViewColumnInfo::TYPE_BITMAP_DATA && !isLinkNode())
577 __SS__ <<
"Can not get fixed choices of node with value type of '" << getValueType() <<
".' Node must be a link or a value node with type '"
578 << TableViewColumnInfo::TYPE_BITMAP_DATA <<
"' or '" << TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA <<
".'" << __E__;
580 ss << nodeDump() << __E__;
584 std::vector<std::string> retVec;
588 if(!linkParentConfig_)
590 __SS__ <<
"Can not get fixed choices of node with no parent config view pointer!" << __E__;
592 ss << nodeDump() << __E__;
602 const TableView* parentView = &(linkParentConfig_->getView());
603 int c = parentView->findCol(linkColName_);
605 std::pair<
unsigned int ,
unsigned int > linkPair;
607 parentView->getChildLink(c, isGroupLink, linkPair);
610 std::vector<std::string> choices = parentView->getColumnInfo(c).getDataChoices();
611 for(
const auto& choice : choices)
612 retVec.push_back(choice);
619 __SS__ <<
"Can not get fixed choices of node with no config view pointer!" << __E__;
621 ss << nodeDump() << __E__;
626 retVec.push_back(tableView_->getColumnInfo(col_).getDefaultValue());
627 std::vector<std::string> choices = tableView_->getColumnInfo(col_).getDataChoices();
628 for(
const auto& choice : choices)
629 retVec.push_back(choice);
642 const std::string& ConfigurationTree::getValueAsString(
bool returnLinkTableValue)
const
648 if(returnLinkTableValue)
649 return linkColValue_;
650 else if(isDisconnected())
651 return ConfigurationTree::DISCONNECTED_VALUE;
652 else if(row_ == TableView::INVALID && col_ == TableView::INVALID)
653 return (groupId_ ==
"") ? table_->getTableName() : groupId_;
654 else if(col_ == TableView::INVALID)
655 return tableView_->getDataView()[row_][tableView_->getColUID()];
658 __SS__ <<
"Impossible Link." << __E__;
660 ss << nodeDump() << __E__;
664 else if(row_ != TableView::INVALID && col_ != TableView::INVALID)
665 return tableView_->getDataView()[row_][col_];
666 else if(row_ == TableView::INVALID && col_ == TableView::INVALID)
670 return ConfigurationTree::ROOT_NAME;
672 return (groupId_ ==
"") ? table_->getTableName() : groupId_;
674 else if(row_ == TableView::INVALID)
676 __SS__ <<
"Malformed ConfigurationTree" << __E__;
678 ss << nodeDump() << __E__;
681 else if(col_ == TableView::INVALID)
682 return tableView_->getDataView()[row_][tableView_->getColUID()];
685 __SS__ <<
"Impossible." << __E__;
687 ss << nodeDump() << __E__;
696 const std::string& ConfigurationTree::getUIDAsString(
void)
const
698 if(isValueNode() || isUIDLinkNode() || isUIDNode())
699 return tableView_->getDataView()[row_][tableView_->getColUID()];
702 __SS__ <<
"Can not get UID of node with type '" << getNodeType() <<
".' Node type must be '" << ConfigurationTree::NODE_TYPE_VALUE <<
"' or '"
703 << ConfigurationTree::NODE_TYPE_UID_LINK <<
".'" << __E__;
705 ss << nodeDump() << __E__;
713 const std::string& ConfigurationTree::getValueDataType(
void)
const
716 return tableView_->getColumnInfo(col_).getDataType();
718 return TableViewColumnInfo::DATATYPE_STRING;
724 bool ConfigurationTree::isDefaultValue(
void)
const
729 if(getValueDataType() == TableViewColumnInfo::DATATYPE_STRING)
731 if(getValueType() == TableViewColumnInfo::TYPE_ON_OFF || getValueType() == TableViewColumnInfo::TYPE_TRUE_FALSE ||
732 getValueType() == TableViewColumnInfo::TYPE_YES_NO)
733 return getValueAsString() == TableViewColumnInfo::DATATYPE_BOOL_DEFAULT;
735 else if(getValueType() == TableViewColumnInfo::TYPE_COMMENT)
736 return getValueAsString() == TableViewColumnInfo::DATATYPE_COMMENT_DEFAULT ||
737 getValueAsString() ==
"";
739 return getValueAsString() == TableViewColumnInfo::DATATYPE_STRING_DEFAULT;
741 else if(getValueDataType() == TableViewColumnInfo::DATATYPE_NUMBER)
742 return getValueAsString() == TableViewColumnInfo::DATATYPE_NUMBER_DEFAULT;
743 else if(getValueDataType() == TableViewColumnInfo::DATATYPE_TIME)
744 return getValueAsString() == TableViewColumnInfo::DATATYPE_TIME_DEFAULT;
752 const std::string& ConfigurationTree::getDefaultValue(
void)
const
756 __SS__ <<
"Can only get default value from a value node! "
757 <<
"The node type is " << getNodeType() << __E__;
759 ss << nodeDump() << __E__;
763 if(getValueDataType() == TableViewColumnInfo::DATATYPE_STRING)
765 if(getValueType() == TableViewColumnInfo::TYPE_ON_OFF || getValueType() == TableViewColumnInfo::TYPE_TRUE_FALSE ||
766 getValueType() == TableViewColumnInfo::TYPE_YES_NO)
767 return TableViewColumnInfo::DATATYPE_BOOL_DEFAULT;
769 else if(getValueType() == TableViewColumnInfo::TYPE_COMMENT)
770 return TableViewColumnInfo::DATATYPE_COMMENT_DEFAULT;
772 return TableViewColumnInfo::DATATYPE_STRING_DEFAULT;
774 else if(getValueDataType() == TableViewColumnInfo::DATATYPE_NUMBER)
775 return TableViewColumnInfo::DATATYPE_NUMBER_DEFAULT;
776 else if(getValueDataType() == TableViewColumnInfo::DATATYPE_TIME)
777 return TableViewColumnInfo::DATATYPE_TIME_DEFAULT;
780 __SS__ <<
"Can only get default value from a value node! "
781 <<
"The node type is " << getNodeType() << __E__;
783 ss << nodeDump() << __E__;
791 const std::string& ConfigurationTree::getValueType(
void)
const
794 return tableView_->getColumnInfo(col_).getType();
795 else if(isLinkNode() && isDisconnected())
796 return ConfigurationTree::VALUE_TYPE_DISCONNECTED;
798 return ConfigurationTree::VALUE_TYPE_NODE;
807 return tableView_->getColumnInfo(col_);
810 __SS__ <<
"Can only get column info from a value node! "
811 <<
"The node type is " << getNodeType() << __E__;
813 ss << nodeDump() << __E__;
820 const unsigned int& ConfigurationTree::getRow(
void)
const {
return row_; }
824 const unsigned int& ConfigurationTree::getColumn(
void)
const {
return col_; }
829 const unsigned int& ConfigurationTree::getFieldRow(
void)
const
843 const unsigned int& ConfigurationTree::getFieldColumn(
void)
const
856 const std::string& ConfigurationTree::getChildLinkIndex(
void)
const
860 __SS__ <<
"Can only get link ID from a link! "
861 <<
"The node type is " << getNodeType() << __E__;
863 ss << nodeDump() << __E__;
866 return childLinkIndex_;
872 const std::string& ConfigurationTree::getValueName(
void)
const
875 return tableView_->getColumnInfo(col_).getName();
876 else if(isLinkNode())
880 __SS__ <<
"Can only get value name of a value node!" << __E__;
882 ss << nodeDump() << __E__;
891 const std::string& childPath,
892 bool doNotThrowOnBrokenUIDLinks,
893 const std::string& originalNodeString)
897 if(childPath.length() <= 1)
899 return tree.recursiveGetNode(childPath, doNotThrowOnBrokenUIDLinks, originalNodeString);
937 ConfigurationTree ConfigurationTree::getNode(
const std::string& nodeString,
bool doNotThrowOnBrokenUIDLinks)
const
939 return recursiveGetNode(nodeString, doNotThrowOnBrokenUIDLinks,
"" );
941 ConfigurationTree ConfigurationTree::recursiveGetNode(
const std::string& nodeString,
942 bool doNotThrowOnBrokenUIDLinks,
943 const std::string& originalNodeString)
const
950 if(nodeString.length() < 1)
952 __SS__ <<
"Invalid empty node name! Looking for child node from node '" << getValue() <<
"'..." << __E__;
954 ss << nodeDump() << __E__;
958 bool startingSlash = nodeString[0] ==
'/';
960 std::string nodeName = nodeString.substr(startingSlash ? 1 : 0, nodeString.find(
'/', 1) - (startingSlash ? 1 : 0));
963 std::string childPath = nodeString.substr(nodeName.length() + (startingSlash ? 1 : 0));
976 return recurse(configMgr_->getNode(nodeName), childPath, doNotThrowOnBrokenUIDLinks, originalNodeString);
978 else if(row_ == TableView::INVALID && col_ == TableView::INVALID)
984 __SS__ <<
"Missing configView pointer! Likely attempting to access a "
985 "child node through a disconnected link node."
988 ss << nodeDump() << __E__;
1000 TableView::INVALID ,
1005 (groupId_ ==
"") ? tableView_->findRow(tableView_->getColUID(), nodeName)
1006 : tableView_->findRowInGroup(tableView_->getColUID(), nodeName, groupId_, childLinkIndex_)),
1008 doNotThrowOnBrokenUIDLinks,
1009 originalNodeString);
1011 else if(row_ == TableView::INVALID)
1013 __SS__ <<
"Malformed ConfigurationTree" << __E__;
1015 ss << nodeDump() << __E__;
1018 else if(col_ == TableView::INVALID)
1034 __SS__ <<
"Missing configView pointer! Likely attempting to access a "
1035 "child node through a disconnected link node."
1038 ss << nodeDump() << __E__;
1042 unsigned int c = tableView_->findCol(nodeName);
1043 std::pair<
unsigned int ,
unsigned int > linkPair;
1044 bool isGroupLink, isLink;
1045 if((isLink = tableView_->getChildLink(c, isGroupLink, linkPair)) && !isGroupLink)
1055 childConfig = configMgr_->getTableByName(tableView_->getDataView()[row_][linkPair.first]);
1056 childConfig->getView();
1058 if(doNotThrowOnBrokenUIDLinks)
1060 childConfig->getView().findRow(childConfig->getView().getColUID(), tableView_->getDataView()[row_][linkPair.second]);
1078 tableView_->getDataView()[row_][c],
1083 tableView_->getDataView()[row_][linkPair.first],
1086 tableView_->getDataView()[row_][linkPair.second],
1089 tableView_->getColumnInfo(c).getChildLinkIndex());
1098 tableView_->getDataView()[row_][c],
1105 tableView_->getColumnInfo(c).getChildLinkIndex(),
1106 childConfig->getView().findRow(childConfig->getView().getColUID(), tableView_->getDataView()[row_][linkPair.second])),
1108 doNotThrowOnBrokenUIDLinks,
1109 originalNodeString);
1121 childConfig = configMgr_->getTableByName(tableView_->getDataView()[row_][linkPair.first]);
1122 childConfig->getView();
1126 if(tableView_->getDataView()[row_][linkPair.first] != TableViewColumnInfo::DATATYPE_LINK_DEFAULT)
1127 __COUT_WARN__ <<
"Found disconnected node! Failed link target "
1129 << nodeName <<
" to table:id=" << tableView_->getDataView()[row_][linkPair.first] <<
":"
1130 << tableView_->getDataView()[row_][linkPair.second] << __E__;
1135 tableView_->getDataView()[row_][linkPair.second],
1138 tableView_->getDataView()[row_][c],
1143 tableView_->getDataView()[row_][linkPair.first],
1146 tableView_->getDataView()[row_][linkPair.second],
1149 tableView_->getColumnInfo(c).getChildLinkIndex());
1155 tableView_->getDataView()[row_][linkPair.second],
1158 tableView_->getDataView()[row_][c],
1165 tableView_->getColumnInfo(c).getChildLinkIndex()),
1167 doNotThrowOnBrokenUIDLinks,
1168 originalNodeString);
1180 TableView::INVALID ,
1181 TableView::INVALID ,
1190 catch(std::runtime_error& e)
1192 __SS__ <<
"\n\nError occurred descending from node '" << getValue() <<
"' in table '" << getTableName() <<
"' looking for child '" << nodeName
1195 ss <<
"The original node search string was '" << originalNodeString <<
".'" << __E__;
1196 ss <<
"--- Additional error detail: \n\n" << e.what() << __E__;
1198 ss << nodeDump() << __E__;
1203 __SS__ <<
"\n\nError occurred descending from node '" << getValue() <<
"' in table '" << getTableName() <<
"' looking for child '" << nodeName
1206 ss <<
"The original node search string was '" << originalNodeString <<
".'" << __E__;
1208 ss << nodeDump() << __E__;
1213 __SS__ <<
"\n\nError occurred descending from node '" << getValue() <<
"' in table '" << getTableName() <<
"' looking for child '" << nodeName <<
"'\n\n"
1214 <<
"Invalid depth! getNode() called from a value point in the Configuration Tree." << __E__;
1215 ss <<
"The original node search string was '" << originalNodeString <<
".'" << __E__;
1217 ss << nodeDump() << __E__;
1224 std::string ConfigurationTree::nodeDump(
void)
const
1226 __SS__ << __E__ << __E__;
1228 ss <<
"Row=" << (int)row_ <<
", Col=" << (
int)col_ << ", TablePointer=" << table_ << __E__;
1232 ss <<
"\n\n" << StringMacros::stackTrace() << __E__ << __E__;
1238 ss <<
"ConfigurationTree::nodeDump() "
1239 "=====================================\nConfigurationTree::nodeDump():"
1246 <<
"Error occurred from node '" << getValueAsString() <<
"'..." << __E__;
1254 <<
"Error occurred from node '" << getValue() <<
"' in table '" << getTableName() <<
".'" << __E__;
1261 auto children = getChildrenNames();
1263 <<
"Here is the list of possible children (count = " << children.size() <<
"):" << __E__;
1264 for(
auto& child : children)
1265 ss <<
"\t\t" << child << __E__;
1268 ss <<
"\n\nHere is the culprit table printout:\n\n";
1269 tableView_->print(ss);
1276 ss <<
"end ConfigurationTree::nodeDump() =====================================" << __E__;
1282 ConfigurationTree ConfigurationTree::getBackNode(std::string nodeName,
unsigned int backSteps)
const
1284 for(
unsigned int i = 0; i < backSteps; i++)
1285 nodeName = nodeName.substr(0, nodeName.find_last_of(
'/'));
1287 return getNode(nodeName);
1291 ConfigurationTree ConfigurationTree::getForwardNode(std::string nodeName,
unsigned int forwardSteps)
const
1296 while(s < nodeName.length() && nodeName[s] ==
'/')
1299 for(
unsigned int i = 0; i < forwardSteps; i++)
1300 s = nodeName.find(
'/', s) + 1;
1302 return getNode(nodeName.substr(0, s));
1308 bool ConfigurationTree::isValueNode(
void)
const {
return (row_ != TableView::INVALID && col_ != TableView::INVALID); }
1313 bool ConfigurationTree::isValueBoolType(
void)
const {
return isValueNode() && tableView_->getColumnInfo(col_).isBoolType(); }
1318 bool ConfigurationTree::isValueNumberDataType(
void)
const
1320 return isValueNode() && tableView_->getColumnInfo(col_).isNumberDataType();
1328 bool ConfigurationTree::isDisconnected(
void)
const
1332 __SS__ <<
"\n\nError occurred testing link connection at node with value '" << getValue() <<
"' in table '" << getTableName() <<
"'\n\n" << __E__;
1333 ss <<
"This is not a Link node! It is node type '" << getNodeType() <<
".' Only a Link node can be disconnected." << __E__;
1335 ss << nodeDump() << __E__;
1339 return !table_ || !tableView_;
1345 bool ConfigurationTree::isLinkNode(
void)
const {
return linkColName_ !=
""; }
1350 const std::string ConfigurationTree::NODE_TYPE_GROUP_TABLE =
"GroupTableNode";
1351 const std::string ConfigurationTree::NODE_TYPE_TABLE =
"TableNode";
1352 const std::string ConfigurationTree::NODE_TYPE_GROUP_LINK =
"GroupLinkNode";
1353 const std::string ConfigurationTree::NODE_TYPE_UID_LINK =
"UIDLinkNode";
1354 const std::string ConfigurationTree::NODE_TYPE_VALUE =
"ValueNode";
1355 const std::string ConfigurationTree::NODE_TYPE_UID =
"UIDNode";
1356 const std::string ConfigurationTree::NODE_TYPE_ROOT =
"RootNode";
1358 std::string ConfigurationTree::getNodeType(
void)
const
1361 return ConfigurationTree::NODE_TYPE_ROOT;
1362 if(isTableNode() && groupId_ !=
"")
1363 return ConfigurationTree::NODE_TYPE_GROUP_TABLE;
1365 return ConfigurationTree::NODE_TYPE_TABLE;
1366 if(isGroupLinkNode())
1367 return ConfigurationTree::NODE_TYPE_GROUP_LINK;
1369 return ConfigurationTree::NODE_TYPE_UID_LINK;
1371 return ConfigurationTree::NODE_TYPE_VALUE;
1372 return ConfigurationTree::NODE_TYPE_UID;
1378 bool ConfigurationTree::isGroupLinkNode(
void)
const {
return (isLinkNode() && groupId_ !=
""); }
1383 bool ConfigurationTree::isUIDLinkNode(
void)
const {
return (isLinkNode() && groupId_ ==
""); }
1388 bool ConfigurationTree::isGroupIDNode(
void)
const {
return (isValueNode() && tableView_->getColumnInfo(col_).isGroupID()); }
1393 bool ConfigurationTree::isUIDNode(
void)
const {
return (row_ != TableView::INVALID && col_ == TableView::INVALID); }
1411 std::vector<ConfigurationTree::RecordField> ConfigurationTree::getCommonFields(
const std::vector<std::string /*uid*/>& recordList,
1412 const std::vector<std::string /*relative-path*/>& fieldAcceptList,
1413 const std::vector<std::string /*relative-path*/>& fieldRejectList,
1415 bool autoSelectFilterFields)
const
1418 if(!isRootNode() && !isTableNode())
1420 __SS__ <<
"Can only get getCommonFields from a root or table node! "
1421 <<
"The node type is " << getNodeType() << __E__;
1423 ss << nodeDump() << __E__;
1427 std::vector<ConfigurationTree::RecordField> fieldCandidateList;
1428 std::vector<int> fieldCount;
1472 if(!recordList.size() && tableView_)
1474 const std::vector<TableViewColumnInfo>& colInfo = tableView_->getColumnsInfo();
1476 for(
unsigned int col = 0; col < colInfo.size(); ++col)
1482 found = fieldAcceptList.size() ?
false :
true;
1484 for(
const auto& fieldFilter : fieldAcceptList)
1485 if(StringMacros::wildCardMatch(fieldFilter, colInfo[col].getName()))
1496 for(
const auto& fieldFilter : fieldRejectList)
1497 if(StringMacros::wildCardMatch(fieldFilter, colInfo[col].getName()))
1510 if(colInfo[col].isChildLink())
1516 std::pair<
unsigned int ,
unsigned int > linkPair;
1518 tableView_->getChildLink(col, isGroupLink, linkPair);
1524 tableView_->getColumnInfo(linkPair.first).getName(),
1526 &tableView_->getColumnInfo(linkPair.first)));
1527 fieldCount.push_back(-1);
1531 tableView_->getColumnInfo(linkPair.second).getName(),
1533 &tableView_->getColumnInfo(linkPair.second)));
1534 fieldCount.push_back(-1);
1540 colInfo[col].getName(),
1543 fieldCount.push_back(1);
1549 for(
unsigned int i = 0; i < recordList.size(); ++i)
1554 node.recursiveGetCommonFields(fieldCandidateList,
1565 __COUT__ <<
"======================= check for count = " <<
1566 (int)recordList.size() << __E__;
1570 for(
unsigned int i = 0; i < fieldCandidateList.size(); ++i)
1572 __COUT__ <<
"Checking " << fieldCandidateList[i].relativePath_ <<
1573 fieldCandidateList[i].columnName_ <<
" = " <<
1574 fieldCount[i] << __E__;
1575 if(recordList.size() != 0 && fieldCount[i] != -1 &&
1576 fieldCount[i] != (int)recordList.size())
1581 fieldCount.erase(fieldCount.begin() + i);
1582 fieldCandidateList.erase(fieldCandidateList.begin() + i);
1591 if(autoSelectFilterFields)
1595 std::set<std::pair<
unsigned int ,
unsigned int >> prioritySet;
1597 unsigned int highestPriority = 0;
1598 unsigned int priorityPenalty;
1599 for(
unsigned int i = 0; i < fieldCandidateList.size(); ++i)
1608 std::count(fieldCandidateList[i].relativePath_.begin(), fieldCandidateList[i].relativePath_.end(),
'/') * 20;
1610 if(fieldCandidateList[i].columnInfo_->isBoolType())
1612 prioritySet.emplace(std::make_pair(0 + priorityPenalty , i ));
1613 if(highestPriority < 0 + priorityPenalty)
1614 highestPriority = 0 + priorityPenalty;
1616 else if(fieldCandidateList[i].columnInfo_->isGroupID())
1618 prioritySet.emplace(std::make_pair(1 + priorityPenalty , i ));
1619 if(highestPriority < 1 + priorityPenalty)
1620 highestPriority = 1 + priorityPenalty;
1622 else if(fieldCandidateList[i].columnInfo_->getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
1624 prioritySet.emplace(std::make_pair(3 + priorityPenalty , i ));
1625 if(highestPriority < 3 + priorityPenalty)
1626 highestPriority = 3 + priorityPenalty;
1628 else if(fieldCandidateList[i].columnInfo_->getType() == TableViewColumnInfo::TYPE_DATA)
1630 prioritySet.emplace(std::make_pair(10 + priorityPenalty , i ));
1631 if(highestPriority < 10 + priorityPenalty)
1632 highestPriority = 10 + priorityPenalty;
1636 fieldCandidateList[i].tableName_ =
"";
1642 __COUTV__(StringMacros::setToString(prioritySet));
1647 unsigned int cnt = 0;
1648 for(
const auto& priorityFieldIndex : prioritySet)
1658 fieldCandidateList[priorityFieldIndex.second].tableName_ =
"";
1662 for(
unsigned int i = 0; i < fieldCandidateList.size(); ++i)
1664 if(fieldCandidateList[i].tableName_ ==
"")
1669 fieldCandidateList.erase(fieldCandidateList.begin() + i);
1675 for(
unsigned int i = 0; i < fieldCandidateList.size(); ++i)
1676 __COUT__ <<
"Final " << fieldCandidateList[i].relativePath_ << fieldCandidateList[i].columnName_ << __E__;
1678 return fieldCandidateList;
1687 std::set<std::string > ConfigurationTree::getUniqueValuesForField(
const std::vector<std::string /*relative-path*/>& recordList,
1688 const std::string& fieldName,
1689 std::string* fieldGroupIDChildLinkIndex )
const
1691 if(fieldGroupIDChildLinkIndex)
1692 *fieldGroupIDChildLinkIndex =
"";
1697 __SS__ <<
"Can only get getCommonFields from a table node! "
1698 <<
"The node type is " << getNodeType() << __E__;
1700 ss << nodeDump() << __E__;
1704 std::set<std::string > uniqueValues;
1712 if(!recordList.size() && tableView_ && fieldGroupIDChildLinkIndex)
1714 const TableViewColumnInfo& colInfo = tableView_->getColumnInfo(tableView_->findCol(fieldName));
1716 if(colInfo.isGroupID())
1717 *fieldGroupIDChildLinkIndex = colInfo.getChildLinkIndex();
1721 for(
unsigned int i = 0; i < recordList.size(); ++i)
1734 if(node.isGroupIDNode())
1741 if(i == 0 && fieldGroupIDChildLinkIndex)
1742 *fieldGroupIDChildLinkIndex = node.getColumnInfo().getChildLinkIndex();
1746 std::set<std::string> setOfGroupIDs = node.getSetOfGroupIDs();
1747 for(
auto& groupID : setOfGroupIDs)
1748 uniqueValues.emplace(groupID);
1751 uniqueValues.emplace(node.getValueAsString(
true));
1755 return uniqueValues;
1761 void ConfigurationTree::recursiveGetCommonFields(std::vector<ConfigurationTree::RecordField>& fieldCandidateList,
1762 std::vector<int>& fieldCount,
1763 const std::vector<std::string /*relative-path*/>& fieldAcceptList,
1764 const std::vector<std::string /*relative-path*/>& fieldRejectList,
1766 const std::string& relativePathBase,
1767 bool inFirstRecord)
const
1795 auto tableName = getTableName();
1796 auto uid = getUIDAsString();
1799 auto recordChildren = getChildren();
1800 for(
const auto& fieldNode : recordChildren)
1806 if(fieldNode.second.isValueNode() || fieldNode.second.isGroupLinkNode())
1809 if(fieldNode.second.isValueNode())
1811 if(fieldNode.second.getColumnInfo().getType() == TableViewColumnInfo::TYPE_AUTHOR ||
1812 fieldNode.second.getColumnInfo().getType() == TableViewColumnInfo::TYPE_TIMESTAMP)
1825 found = fieldAcceptList.size() ?
false :
true;
1827 for(
const auto& fieldFilter : fieldAcceptList)
1828 if(fieldFilter.find(
'/') != std::string::npos)
1831 if(StringMacros::wildCardMatch(fieldFilter, relativePathBase + fieldNode.first))
1837 else if(StringMacros::wildCardMatch(fieldFilter, fieldNode.first))
1848 for(
const auto& fieldFilter : fieldRejectList)
1849 if(fieldFilter.find(
'/') != std::string::npos)
1852 if(StringMacros::wildCardMatch(fieldFilter, relativePathBase + fieldNode.first))
1858 else if(StringMacros::wildCardMatch(fieldFilter, fieldNode.first))
1871 if(fieldNode.second.isGroupLinkNode())
1877 std::pair<
unsigned int ,
unsigned int > linkPair;
1879 tableView_->getChildLink(tableView_->findCol(fieldNode.first), isGroupLink, linkPair);
1885 tableView_->getColumnInfo(linkPair.first).getName(),
1887 &tableView_->getColumnInfo(linkPair.first)));
1888 fieldCount.push_back(1);
1892 tableView_->getColumnInfo(linkPair.second).getName(),
1894 &tableView_->getColumnInfo(linkPair.second)));
1895 fieldCount.push_back(1);
1903 &fieldNode.second.getColumnInfo()));
1904 fieldCount.push_back(1);
1912 for(j = 0; j < fieldCandidateList.size(); ++j)
1914 if((relativePathBase + fieldNode.first) ==
1915 (fieldCandidateList[j].relativePath_ + fieldCandidateList[j].columnName_))
1921 if(fieldNode.second.isGroupLinkNode() && j+1 < fieldCandidateList.size())
1928 else if(fieldNode.second.isUIDLinkNode())
1936 found = fieldAcceptList.size() ?
false :
true;
1937 for(
const auto& fieldFilter : fieldAcceptList)
1938 if(fieldFilter.find(
'/') != std::string::npos)
1941 if(StringMacros::wildCardMatch(fieldFilter, relativePathBase + fieldNode.first))
1947 else if(StringMacros::wildCardMatch(fieldFilter, fieldNode.first))
1958 for(
const auto& fieldFilter : fieldRejectList)
1959 if(fieldFilter.find(
'/') != std::string::npos)
1962 if(StringMacros::wildCardMatch(fieldFilter, relativePathBase + fieldNode.first))
1968 else if(StringMacros::wildCardMatch(fieldFilter, fieldNode.first))
1980 std::pair<
unsigned int ,
unsigned int > linkPair;
1984 tableView_->getChildLink(tableView_->findCol(fieldNode.first), isGroupLink, linkPair);
1990 tableView_->getColumnInfo(linkPair.first).getName(),
1992 &tableView_->getColumnInfo(linkPair.first)));
1993 fieldCount.push_back(1);
1997 tableView_->getColumnInfo(linkPair.second).getName(),
1999 &tableView_->getColumnInfo(linkPair.second)));
2000 fieldCount.push_back(1);
2007 for(j = 0; j < fieldCandidateList.size()-1; ++j)
2009 if((relativePathBase + fieldNode.first) ==
2010 (fieldCandidateList[j].relativePath_ + fieldCandidateList[j].columnName_))
2023 if(depth > 0 && !fieldNode.second.isDisconnected())
2024 fieldNode.second.recursiveGetCommonFields(fieldCandidateList,
2029 (relativePathBase + fieldNode.first) +
"/",
2042 std::vector<std::vector<std::pair<std::string, ConfigurationTree>>> ConfigurationTree::getChildrenByPriority(
2043 std::map<std::string /*relative-path*/, std::string /*value*/> filterMap,
bool onlyStatusTrue)
const
2045 std::vector<std::vector<std::pair<std::string, ConfigurationTree>>> retVector;
2049 bool filtering = filterMap.size();
2051 std::string fieldValue;
2053 bool createContainer;
2055 std::vector<std::vector<std::string>> childrenNamesByPriority = getChildrenNamesByPriority(onlyStatusTrue);
2057 for(
auto& childNamesAtPriority : childrenNamesByPriority)
2059 createContainer =
true;
2061 for(
auto& childName : childNamesAtPriority)
2071 for(
const auto& filterPair : filterMap)
2073 std::string filterPath = childName +
"/" + filterPair.first;
2074 __COUTV__(filterPath);
2078 std::vector<std::string> fieldValues;
2079 StringMacros::getVectorFromString(filterPair.second, fieldValues, std::set<char>({
','}) );
2081 __COUTV__(fieldValues.size());
2085 for(
const auto& fieldValue : fieldValues)
2096 __COUT__ <<
"\t\tCheck: " << filterPair.first <<
" == " << fieldValue <<
" => " << StringMacros::decodeURIComponent(fieldValue)
2097 <<
" ??? " << this->getNode(filterPath).getValueAsString(
true) << __E__;
2099 if(StringMacros::wildCardMatch(StringMacros::decodeURIComponent(fieldValue), this->getNode(filterPath).getValueAsString(
true)))
2109 __SS__ <<
"Failed to access filter path '" << filterPath <<
"' - aborting." << __E__;
2111 ss << nodeDump() << __E__;
2128 retVector.push_back(std::vector<std::pair<std::string, ConfigurationTree>>());
2129 createContainer =
false;
2132 retVector[retVector.size() - 1].push_back(std::pair<std::string, ConfigurationTree>(childName, this->getNode(childName,
true)));
2149 std::vector<std::pair<std::string, ConfigurationTree>> ConfigurationTree::getChildren(std::map<std::string /*relative-path*/, std::string /*value*/> filterMap,
2151 bool onlyStatusTrue)
const
2153 std::vector<std::pair<std::string, ConfigurationTree>> retVector;
2157 bool filtering = filterMap.size();
2159 std::string fieldValue;
2161 std::vector<std::string> childrenNames = getChildrenNames(byPriority, onlyStatusTrue);
2162 for(
auto& childName : childrenNames)
2172 for(
const auto& filterPair : filterMap)
2174 std::string filterPath = childName +
"/" + filterPair.first;
2175 __COUTV__(filterPath);
2181 std::vector<std::string> fieldValues;
2182 StringMacros::getVectorFromString(filterPair.second, fieldValues, std::set<char>({
','}) );
2184 __COUTV__(fieldValues.size());
2188 for(
const auto& fieldValue : fieldValues)
2198 if(childNode.isGroupIDNode())
2202 bool groupIdFound =
false;
2203 std::set<std::string> setOfGroupIDs = childNode.getSetOfGroupIDs();
2205 for(
auto& groupID : setOfGroupIDs)
2207 __COUT__ <<
"\t\tGroupID Check: " << filterPair.first <<
" == " << fieldValue <<
" => "
2208 << StringMacros::decodeURIComponent(fieldValue) <<
" ??? " << groupID << __E__;
2210 if(StringMacros::wildCardMatch(StringMacros::decodeURIComponent(fieldValue), groupID))
2213 __COUT__ <<
"Found match" << __E__;
2214 groupIdFound =
true;
2222 __COUT__ <<
"Found break match" << __E__;
2229 __COUT__ <<
"\t\tCheck: " << filterPair.first <<
" == " << fieldValue <<
" => " << StringMacros::decodeURIComponent(fieldValue)
2230 <<
" ??? " << childNode.getValueAsString(
true) << __E__;
2232 if(StringMacros::wildCardMatch(StringMacros::decodeURIComponent(fieldValue), childNode.getValueAsString(
true)))
2243 __SS__ <<
"Failed to access filter path '" << filterPath <<
"' - aborting." << __E__;
2245 ss << nodeDump() << __E__;
2260 retVector.push_back(std::pair<std::string, ConfigurationTree>(childName, this->getNode(childName,
true)));
2270 std::map<std::string, ConfigurationTree> ConfigurationTree::getChildrenMap(
void)
const
2272 std::map<std::string, ConfigurationTree> retMap;
2276 std::vector<std::string> childrenNames = getChildrenNames();
2277 for(
auto& childName : childrenNames)
2280 retMap.insert(std::pair<std::string, ConfigurationTree>(childName, this->getNode(childName)));
2288 inline bool ConfigurationTree::isRootNode(
void)
const {
return (!table_); }
2291 inline bool ConfigurationTree::isTableNode(
void)
const {
return (table_ && row_ == TableView::INVALID && col_ == TableView::INVALID); }
2295 bool ConfigurationTree::isEnabled(
void)
const
2299 __SS__ <<
"Can not get status of '" << getValueAsString() <<
2300 ".' Can only check the status of a UID/Record node!" << __E__;
2305 tableView_->getValue(tmpStatus, row_, tableView_->getColStatus());
2310 bool ConfigurationTree::isStatusNode(
void)
const
2315 return col_ == tableView_->getColStatus();
2321 std::vector<std::vector<std::string>> ConfigurationTree::getChildrenNamesByPriority(
bool onlyStatusTrue)
const
2323 std::vector<std::vector<std::string >> retVector;
2327 __SS__ <<
"Can not get children names of '" << getValueAsString() <<
"' with null configuration view pointer!" << __E__;
2328 if(isLinkNode() && isDisconnected())
2329 ss <<
" This node is a disconnected link to " << getDisconnectedTableName() << __E__;
2331 ss << nodeDump() << __E__;
2335 if(row_ == TableView::INVALID && col_ == TableView::INVALID)
2342 std::vector<std::vector<
unsigned int >> groupRowsByPriority = tableView_->getGroupRowsByPriority(
2343 groupId_ ==
"" ? TableView::INVALID :
2344 tableView_->getLinkGroupIDColumn(childLinkIndex_),
2349 for(
const auto& priorityChildRowVector : groupRowsByPriority)
2351 retVector.push_back(std::vector<std::string /*child name*/>());
2352 for(
const auto& priorityChildRow : priorityChildRowVector)
2353 retVector[retVector.size() - 1].push_back(tableView_->getDataView()[priorityChildRow][tableView_->getColUID()]);
2357 else if(row_ == TableView::INVALID)
2359 __SS__ <<
"Malformed ConfigurationTree" << __E__;
2361 ss << nodeDump() << __E__;
2364 else if(col_ == TableView::INVALID)
2369 for(
unsigned int c = 0; c < tableView_->getNumberOfColumns(); ++c)
2370 if(c == tableView_->getColUID() ||
2372 tableView_->getColumnInfo(c).isChildLinkGroupID() || tableView_->getColumnInfo(c).isChildLinkUID())
2376 retVector.push_back(std::vector<std::string /*child name*/>());
2377 retVector[retVector.size() - 1].push_back(tableView_->getColumnInfo(c).getName());
2383 __SS__ <<
"\n\nError occurred looking for children of nodeName=" << getValueName() <<
"\n\n"
2384 <<
"Invalid depth! getChildrenValues() called from a value point in the "
2385 "Configuration Tree."
2388 ss << nodeDump() << __E__;
2398 std::vector<std::string> ConfigurationTree::getChildrenNames(
bool byPriority,
bool onlyStatusTrue)
const
2400 std::vector<std::string > retVector;
2404 __SS__ <<
"Can not get children names of '" << getValueAsString() <<
"' with null configuration view pointer!" << __E__;
2405 if(isLinkNode() && isDisconnected())
2406 ss <<
" This node is a disconnected link to " << getDisconnectedTableName() << __E__;
2410 if(row_ == TableView::INVALID && col_ == TableView::INVALID)
2414 std::vector<
unsigned int > groupRows =
2415 tableView_->getGroupRows((groupId_ ==
"" ? TableView::INVALID :
2416 tableView_->getLinkGroupIDColumn(childLinkIndex_)),
2422 for(
const auto& groupRow : groupRows)
2423 retVector.push_back(tableView_->getDataView()[groupRow][tableView_->getColUID()]);
2490 else if(row_ == TableView::INVALID)
2492 __SS__ <<
"Malformed ConfigurationTree" << __E__;
2494 ss << nodeDump() << __E__;
2497 else if(col_ == TableView::INVALID)
2502 for(
unsigned int c = 0; c < tableView_->getNumberOfColumns(); ++c)
2503 if(c == tableView_->getColUID() ||
2505 tableView_->getColumnInfo(c).isChildLinkGroupID() || tableView_->getColumnInfo(c).isChildLinkUID())
2508 retVector.push_back(tableView_->getColumnInfo(c).getName());
2513 __SS__ <<
"\n\nError occurred looking for children of nodeName=" << getValueName() <<
"\n\n"
2514 <<
"Invalid depth! getChildrenValues() called from a value point in the "
2515 "Configuration Tree."
2518 ss << nodeDump() << __E__;
2536 __SS__ <<
"Invalid node for get value." << __E__;
2540 std::string valueString = tableView_->getValueAsString(row_, col_,
true );
2542 if(valueString.size() && valueString[0] ==
'/')
2549 __COUT__ <<
"Found a valid tree path in value!" << __E__;
2554 __SS__ <<
"Invalid tree path." << __E__;
2560 __SS__ <<
"Invalid value string '" << valueString <<
"' - must start with a '/' character." << __E__;