1 #include "otsdaq-core/ConfigurationInterface/ConfigurationTree.h"
3 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationBase.h"
4 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
6 #include "otsdaq-core/Macros/StringMacros.h"
7 #if MESSAGEFACILITY_HEX_VERSION > 0x20100
8 #include <boost/stacktrace.hpp>
15 #define __MF_SUBJECT__ "ConfigurationTree"
17 const std::string ConfigurationTree::DISCONNECTED_VALUE =
"X";
18 const std::string ConfigurationTree::VALUE_TYPE_DISCONNECTED =
"Disconnected";
19 const std::string ConfigurationTree::VALUE_TYPE_NODE =
"Node";
22 ConfigurationTree::ConfigurationTree()
26 linkParentConfig_ (0),
31 disconnectedTargetName_ (
""),
32 disconnectedLinkID_ (
""),
56 ConfigurationTree::ConfigurationTree(
59 const std::string& groupId,
61 const std::string& linkColName,
62 const std::string& linkColValue,
63 const unsigned int linkBackRow,
64 const unsigned int linkBackCol,
65 const std::string& disconnectedTargetName,
66 const std::string& disconnectedLinkID,
67 const std::string& childLinkIndex,
68 const unsigned int row,
69 const unsigned int col)
70 : configMgr_ (configMgr),
71 configuration_ (config),
73 linkParentConfig_ (linkParentConfig),
74 linkColName_ (linkColName),
75 linkColValue_ (linkColValue),
76 linkBackRow_ (linkBackRow),
77 linkBackCol_ (linkBackCol),
78 disconnectedTargetName_ (disconnectedTargetName),
79 disconnectedLinkID_ (disconnectedLinkID),
80 childLinkIndex_ (childLinkIndex),
90 ss << __COUT_HDR_FL__ <<
"Invalid empty pointer given to tree!\n" <<
91 "\n\tconfigMgr_=" << configMgr_ <<
92 "\n\tconfiguration_=" << configuration_ <<
93 "\n\tconfigView_=" << configView_ <<
95 __COUT__ <<
"\n" << ss.str();
96 throw std::runtime_error(ss.str());
100 configView_ = &(configuration_->getView());
104 configView_->getColumnInfo(configView_->getColUID()).getType() != ViewColumnInfo::TYPE_UID)
106 __SS__ <<
"Missing UID column (must column of type " << ViewColumnInfo::TYPE_UID <<
107 ") in config view : " << configView_->getTableName() << std::endl;
108 __COUT__ <<
"\n" << ss.str();
109 throw std::runtime_error(ss.str());
115 ConfigurationTree::~ConfigurationTree(
void)
126 void ConfigurationTree::print(
const unsigned int &depth, std::ostream &out)
const
128 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() << std::endl;
140 out << space << t.getValueName();
141 if(t.isDisconnected())
143 out <<
" :\t" << t.getValueAsString() << std::endl;
147 (t.isGroupLinkNode()?
"Group":
"U") <<
148 "ID=" << t.getValueAsString() <<
152 out << space << t.getValueAsString() <<
" : " << std::endl;
158 auto C = t.getChildren();
160 out << space <<
"{" << std::endl;
162 recursivePrint(c.second,depth-1,out,space +
" ");
164 out << space <<
"}" << std::endl;
174 void ConfigurationTree::getValue(std::string& value)
const
178 if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID)
185 __COUT__ <<
"Success following path to tree node!" << std::endl;
192 value = configView_->validateValueForColumn(
193 valueAsTreeNode.getValueAsString(),col_);
196 __COUT__ <<
"Successful value!" << std::endl;
210 configView_->getValue(value,row_,col_);
212 else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
214 if(isLinkNode() && isDisconnected())
215 value = (groupId_ ==
"") ? getValueName():groupId_;
217 value = (groupId_ ==
"") ? configuration_->getConfigurationName():groupId_;
219 else if(row_ == ConfigurationView::INVALID)
221 __SS__ <<
"Malformed ConfigurationTree" << std::endl;
222 __COUT_ERR__ << ss.str();
223 throw std::runtime_error(ss.str());
225 else if(col_ == ConfigurationView::INVALID)
226 configView_->getValue(value,row_,configView_->getColUID());
229 __SS__ <<
"Impossible." << std::endl;
230 __COUT_ERR__ << ss.str();
231 throw std::runtime_error(ss.str());
248 std::string ConfigurationTree::getValue()
const
251 ConfigurationTree::getValue(value);
264 if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID)
266 std::string bitmapString;
267 configView_->getValue(bitmapString,row_,col_);
269 __COUTV__(bitmapString);
270 if(bitmapString == ViewColumnInfo::DATATYPE_STRING_DEFAULT)
272 bitmap.isDefault_ =
true;
276 bitmap.isDefault_ =
false;
280 bitmap.bitmap_.clear();
282 bool openRow =
false;
283 unsigned int startInt = -1;
284 for(
unsigned int i=0; i<bitmapString.length(); i++)
286 __COUTV__(bitmapString[i]);
294 if(bitmapString[i] ==
'[')
298 bitmap.bitmap_.push_back(std::vector<uint64_t>());
300 else if(bitmapString[i] ==
']')
304 else if(bitmapString[i] ==
',')
306 __SS__ <<
"Too many ']' or ',' characters in bit map configuration" << std::endl;
310 else if(startInt == (
unsigned int)-1)
312 if(bitmapString[i] ==
']')
316 else if(bitmapString[i] >=
'0' && bitmapString[i] <=
'9')
320 else if(bitmapString[i] ==
',')
322 __SS__ <<
"Too many ',' characters in bit map configuration" << std::endl;
330 if(bitmapString[i] ==
']')
333 bitmap.bitmap_[row].push_back(strtoul(
334 bitmapString.substr(startInt,i-startInt).c_str(),0,0));
337 else if(bitmapString[i] ==
',')
339 bitmap.bitmap_[row].push_back(strtoul(
340 bitmapString.substr(startInt,i-startInt).c_str(),0,0));
346 for(
unsigned int r = 0; r<bitmap.bitmap_.size(); ++r)
348 for(
unsigned int c = 0; c<bitmap.bitmap_[r].size(); ++c)
350 __COUT__ << r <<
"," << c <<
" = " << bitmap.bitmap_[r][c] << __E__;
352 __COUT__ <<
"================" << __E__;
359 __SS__ <<
"Requesting getValue must be on a value node." << std::endl;
360 __COUT_ERR__ << ss.str();
361 throw std::runtime_error(ss.str());
373 ConfigurationTree::getValueAsBitMap(value);
380 std::string ConfigurationTree::getEscapedValue()
const
382 if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID)
383 return configView_->getEscapedValueAsString(row_,col_);
385 __SS__ <<
"Can not get escaped value except from a value node!" <<
386 " This node is type '" << getNodeType() <<
"." << std::endl;
387 __COUT_ERR__ <<
"\n" << ss.str();
388 throw std::runtime_error(ss.str());
393 const std::string& ConfigurationTree::getConfigurationName(
void)
const
397 __SS__ <<
"Can not get configuration name of node with no configuration pointer!" << std::endl;
398 throw std::runtime_error(ss.str());
400 return configuration_->getConfigurationName();
407 const std::string& ConfigurationTree::getFieldConfigurationName(
void)
const
412 if(!linkParentConfig_)
414 __SS__ <<
"Can not get configuration name of link node field with no parent configuration pointer!" << std::endl;
415 throw std::runtime_error(ss.str());
417 return linkParentConfig_->getConfigurationName();
420 return getConfigurationName();
425 const std::string& ConfigurationTree::getDisconnectedTableName(
void)
const
427 if(isLinkNode() && isDisconnected())
return disconnectedTargetName_;
429 __SS__ <<
"Can not get disconnected target name of node unless it is a disconnected link node!" << std::endl;
430 throw std::runtime_error(ss.str());
435 const std::string& ConfigurationTree::getDisconnectedLinkID(
void)
const
437 if(isLinkNode() && isDisconnected())
return disconnectedLinkID_;
439 __SS__ <<
"Can not get disconnected target name of node unless it is a disconnected link node!" << std::endl;
440 throw std::runtime_error(ss.str());
449 __SS__ <<
"Can not get configuration version of node with no config view pointer!" << std::endl;
450 throw std::runtime_error(ss.str());
452 return configView_->getVersion();
457 const time_t& ConfigurationTree::getConfigurationCreationTime(
void)
const
461 __SS__ <<
"Can not get configuration creation time of node with no config view pointer!" << std::endl;
462 throw std::runtime_error(ss.str());
464 return configView_->getCreationTime();
472 std::vector<std::string> ConfigurationTree::getFixedChoices(
void)
const
474 if(getValueType() != ViewColumnInfo::TYPE_FIXED_CHOICE_DATA &&
475 getValueType() != ViewColumnInfo::TYPE_BITMAP_DATA &&
478 __SS__ <<
"Can not get fixed choices of node with value type of '" <<
479 getValueType() <<
".' Node must be a link or a value node with type '" <<
480 ViewColumnInfo::TYPE_BITMAP_DATA <<
"' or '" <<
481 ViewColumnInfo::TYPE_FIXED_CHOICE_DATA <<
".'" << std::endl;
482 throw std::runtime_error(ss.str());
485 std::vector<std::string> retVec;
489 if(!linkParentConfig_)
491 __SS__ <<
"Can not get fixed choices of node with no parent config view pointer!" << std::endl;
492 throw std::runtime_error(ss.str());
502 int c = parentView->findCol(linkColName_);
504 std::pair<
unsigned int ,
unsigned int > linkPair;
506 parentView->getChildLink(c, isGroupLink, linkPair);
509 std::vector<std::string> choices = parentView->getColumnInfo(c).getDataChoices();
510 for(
const auto &choice:choices)
511 retVec.push_back(choice);
518 __SS__ <<
"Can not get fixed choices of node with no config view pointer!" << std::endl;
519 throw std::runtime_error(ss.str());
523 retVec.push_back(configView_->getColumnInfo(col_).getDefaultValue());
524 std::vector<std::string> choices = configView_->getColumnInfo(col_).getDataChoices();
525 for(
const auto &choice:choices)
526 retVec.push_back(choice);
539 const std::string& ConfigurationTree::getValueAsString(
bool returnLinkTableValue)
const
543 if(returnLinkTableValue)
544 return linkColValue_;
545 else if(isDisconnected())
546 return ConfigurationTree::DISCONNECTED_VALUE;
547 else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
548 return (groupId_ ==
"")?configuration_->getConfigurationName():groupId_;
549 else if(col_ == ConfigurationView::INVALID)
550 return configView_->getDataView()[row_][configView_->getColUID()];
553 __SS__ <<
"Impossible Link." << std::endl;
554 __COUT_ERR__ << ss.str();
555 throw std::runtime_error(ss.str());
558 else if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID)
559 return configView_->getDataView()[row_][col_];
560 else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
561 return (groupId_ ==
"")?configuration_->getConfigurationName():groupId_;
562 else if(row_ == ConfigurationView::INVALID)
564 __SS__ <<
"Malformed ConfigurationTree" << std::endl;
565 __COUT_ERR__ << ss.str();
566 throw std::runtime_error(ss.str());
568 else if(col_ == ConfigurationView::INVALID)
569 return configView_->getDataView()[row_][configView_->getColUID()];
572 __SS__ <<
"Impossible." << std::endl;
573 __COUT_ERR__ << ss.str();
574 throw std::runtime_error(ss.str());
582 const std::string& ConfigurationTree::getUIDAsString(
void)
const
584 if(isValueNode() || isUIDLinkNode())
585 return configView_->getDataView()[row_][configView_->getColUID()];
588 __SS__ <<
"Can not get UID of node with type '" <<
589 getNodeType() <<
".' Node type must be '" <<
590 ConfigurationTree::NODE_TYPE_VALUE <<
"' or '" <<
591 ConfigurationTree::NODE_TYPE_UID_LINK <<
".'" << std::endl;
592 throw std::runtime_error(ss.str());
599 const std::string& ConfigurationTree::getValueDataType(
void)
const
602 return configView_->getColumnInfo(col_).getDataType();
604 return ViewColumnInfo::DATATYPE_STRING;
610 bool ConfigurationTree::isDefaultValue(
void)
const
612 if(!isValueNode())
return false;
614 if(getValueDataType() == ViewColumnInfo::DATATYPE_STRING)
616 if(getValueType() == ViewColumnInfo::TYPE_ON_OFF ||
617 getValueType() == ViewColumnInfo::TYPE_TRUE_FALSE ||
618 getValueType() == ViewColumnInfo::TYPE_YES_NO)
619 return getValueAsString() == ViewColumnInfo::DATATYPE_BOOL_DEFAULT;
620 else if(getValueType() == ViewColumnInfo::TYPE_COMMENT)
621 return getValueAsString() == ViewColumnInfo::DATATYPE_COMMENT_DEFAULT ||
622 getValueAsString() ==
"";
624 return getValueAsString() == ViewColumnInfo::DATATYPE_STRING_DEFAULT;
626 else if(getValueDataType() == ViewColumnInfo::DATATYPE_NUMBER)
627 return getValueAsString() == ViewColumnInfo::DATATYPE_NUMBER_DEFAULT;
628 else if(getValueDataType() == ViewColumnInfo::DATATYPE_TIME)
629 return getValueAsString() == ViewColumnInfo::DATATYPE_TIME_DEFAULT;
637 const std::string& ConfigurationTree::getValueType(
void)
const
640 return configView_->getColumnInfo(col_).getType();
641 else if(isLinkNode() && isDisconnected())
642 return ConfigurationTree::VALUE_TYPE_DISCONNECTED;
644 return ConfigurationTree::VALUE_TYPE_NODE;
650 const ViewColumnInfo& ConfigurationTree::getColumnInfo(
void)
const
653 return configView_->getColumnInfo(col_);
656 __SS__ <<
"Can only get column info from a value node! " <<
657 "The node type is " << getNodeType() << std::endl;
658 __COUT__ <<
"\n" << ss.str() << std::endl;
659 throw std::runtime_error(ss.str());
666 const unsigned int& ConfigurationTree::getRow(
void)
const
673 const unsigned int& ConfigurationTree::getColumn(
void)
const
681 const unsigned int& ConfigurationTree::getFieldRow(
void)
const
695 const unsigned int& ConfigurationTree::getFieldColumn(
void)
const
708 const std::string& ConfigurationTree::getChildLinkIndex(
void)
const
712 __SS__ <<
"Can only get link ID from a link! " <<
713 "The node type is " << getNodeType() << std::endl;
714 __COUT__ <<
"\n" << ss.str() << std::endl;
715 throw std::runtime_error(ss.str());
717 return childLinkIndex_;
723 const std::string& ConfigurationTree::getValueName(
void)
const
726 return configView_->getColumnInfo(col_).getName();
727 else if(isLinkNode())
731 __SS__ <<
"Can only get value name of a value node!" << std::endl;
732 __COUT__ <<
"\n" << ss.str() << std::endl;
733 throw std::runtime_error(ss.str());
742 const std::string& childPath,
bool doNotThrowOnBrokenUIDLinks)
746 if(childPath.length() <= 1)
748 return tree.getNode(childPath,doNotThrowOnBrokenUIDLinks);
785 bool doNotThrowOnBrokenUIDLinks)
const
791 if(nodeString.length() < 1)
793 __SS__ <<
"Invalid empty node name! Looking for child node from node '" <<
794 getValue() <<
"'..." << std::endl;
795 __COUT_ERR__ << ss.str();
796 throw std::runtime_error(ss.str());
799 bool startingSlash = nodeString[0] ==
'/';
801 std::string nodeName = nodeString.substr(startingSlash?1:0, nodeString.find(
'/',1)-(startingSlash?1:0));
804 std::string childPath = nodeString.substr(nodeName.length() + (startingSlash?1:0));
818 configMgr_->getNode(nodeName),
819 childPath, doNotThrowOnBrokenUIDLinks);
821 else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
827 __SS__ <<
"Missing configView pointer! Likely attempting to access a child node through a disconnected link node." << std::endl;
828 __COUT_ERR__ <<
"\n" << ss.str();
829 throw std::runtime_error(ss.str());
840 ConfigurationView::INVALID , ConfigurationView::INVALID ,
846 configView_->findRow(configView_->getColUID(),nodeName)
847 : configView_->findRowInGroup(configView_->getColUID(),
848 nodeName,groupId_,childLinkIndex_) ),
849 childPath, doNotThrowOnBrokenUIDLinks);
851 else if(row_ == ConfigurationView::INVALID)
853 __SS__ <<
"Malformed ConfigurationTree" << std::endl;
854 __COUT_ERR__ <<
"\n" << ss.str();
855 throw std::runtime_error(ss.str());
857 else if(col_ == ConfigurationView::INVALID)
871 __SS__ <<
"Missing configView pointer! Likely attempting to access a child node through a disconnected link node." << std::endl;
872 __COUT_ERR__ <<
"\n" << ss.str();
873 throw std::runtime_error(ss.str());
876 unsigned int c = configView_->findCol(nodeName);
877 std::pair<
unsigned int ,
unsigned int > linkPair;
878 bool isGroupLink, isLink;
879 if((isLink = configView_->getChildLink(c, isGroupLink, linkPair)) &&
890 childConfig = configMgr_->getConfigurationByName(configView_->getDataView()[row_][linkPair.first]);
891 childConfig->getView();
893 if(doNotThrowOnBrokenUIDLinks)
895 childConfig->getView().findRow(childConfig->getView().getColUID(),
896 configView_->getDataView()[row_][linkPair.second]);
913 configView_->getDataView()[row_][c],
915 configView_->getDataView()[row_][linkPair.first],
916 configView_->getDataView()[row_][linkPair.second],
917 configView_->getColumnInfo(c).getChildLinkIndex());
927 configView_->getDataView()[row_][c],
931 configView_->getColumnInfo(c).getChildLinkIndex(),
932 childConfig->getView().findRow(childConfig->getView().getColUID(),
933 configView_->getDataView()[row_][linkPair.second])
935 childPath, doNotThrowOnBrokenUIDLinks);
947 childConfig = configMgr_->getConfigurationByName(
948 configView_->getDataView()[row_][linkPair.first]);
949 childConfig->getView();
953 if(configView_->getDataView()[row_][linkPair.first] !=
954 ViewColumnInfo::DATATYPE_LINK_DEFAULT)
955 __COUT_WARN__ <<
"Found disconnected node! Failed link target from nodeName=" <<
956 nodeName <<
" to table:id=" <<
957 configView_->getDataView()[row_][linkPair.first] <<
":" <<
958 configView_->getDataView()[row_][linkPair.second] <<
963 configView_->getDataView()[row_][linkPair.second],
966 configView_->getDataView()[row_][c],
968 configView_->getDataView()[row_][linkPair.first],
969 configView_->getDataView()[row_][linkPair.second],
970 configView_->getColumnInfo(c).getChildLinkIndex()
978 configView_->getDataView()[row_][linkPair.second],
981 configView_->getDataView()[row_][c],
985 configView_->getColumnInfo(c).getChildLinkIndex()
987 childPath, doNotThrowOnBrokenUIDLinks);
998 ConfigurationView::INVALID , ConfigurationView::INVALID ,
1005 catch(std::runtime_error &e)
1007 __SS__ <<
"\n\nError occurred descending from node '" << getValue() <<
1008 "' in table '" << getConfigurationName() <<
1009 "' looking for child '" << nodeName <<
"'\n\n" << std::endl;
1010 ss <<
"--- Additional error detail: \n\n" << e.what() << std::endl;
1011 #if MESSAGEFACILITY_HEX_VERSION > 0x20100
1012 ss << boost::stacktrace::stacktrace();
1014 throw std::runtime_error(ss.str());
1018 __SS__ <<
"\n\nError occurred descending from node '" << getValue() <<
1019 "' in table '" << getConfigurationName() <<
1020 "' looking for child '" << nodeName <<
"'\n\n" << std::endl;
1021 #if MESSAGEFACILITY_HEX_VERSION > 0x20100
1022 ss << boost::stacktrace::stacktrace();
1024 throw std::runtime_error(ss.str());
1028 __SS__ <<
"\n\nError occurred descending from node '" << getValue() <<
1029 "' in table '" << getConfigurationName() <<
1030 "' looking for child '" << nodeName <<
"'\n\n" <<
1031 "Invalid depth! getNode() called from a value point in the Configuration Tree." << std::endl;
1032 #if MESSAGEFACILITY_HEX_VERSION > 0x20100
1033 ss << boost::stacktrace::stacktrace();
1035 throw std::runtime_error(ss.str());
1040 ConfigurationTree ConfigurationTree::getBackNode(std::string nodeName,
unsigned int backSteps)
const
1042 for(
unsigned int i=0; i<backSteps; i++)
1043 nodeName = nodeName.substr(0, nodeName.find_last_of(
'/'));
1045 return getNode(nodeName);
1049 ConfigurationTree ConfigurationTree::getForwardNode(std::string nodeName,
unsigned int forwardSteps)
const
1054 while(s < nodeName.length() && nodeName[s] ==
'/') ++s;
1056 for(
unsigned int i=0; i<forwardSteps; i++)
1057 s = nodeName.find(
'/',s) + 1;
1059 return getNode(nodeName.substr(0,s));
1064 bool ConfigurationTree::isValueNode(
void)
const
1066 return (row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID);
1074 bool ConfigurationTree::isDisconnected(
void)
const
1078 __SS__ <<
"\n\nError occurred testing link connection at node with value '" <<
1080 "' in table '" << getConfigurationName() <<
1081 "'\n\n" << std::endl;
1082 ss <<
"This is not a Link node! It is node type '" <<
1083 getNodeType() <<
".' Only a Link node can be disconnected." << std::endl;
1085 throw std::runtime_error(ss.str());
1088 return !configuration_ || !configView_;
1094 bool ConfigurationTree::isLinkNode(
void)
const
1096 return linkColName_ !=
"";
1102 const std::string ConfigurationTree::NODE_TYPE_GROUP_TABLE =
"GroupConfigurationNode";
1103 const std::string ConfigurationTree::NODE_TYPE_TABLE =
"ConfigurationNode";
1104 const std::string ConfigurationTree::NODE_TYPE_GROUP_LINK =
"GroupLinkNode";
1105 const std::string ConfigurationTree::NODE_TYPE_UID_LINK =
"UIDLinkNode";
1106 const std::string ConfigurationTree::NODE_TYPE_VALUE =
"ValueNode";
1107 const std::string ConfigurationTree::NODE_TYPE_UID =
"UIDNode";
1108 const std::string ConfigurationTree::NODE_TYPE_ROOT =
"RootNode";
1110 std::string ConfigurationTree::getNodeType(
void)
const
1112 if(!configuration_)
return ConfigurationTree::NODE_TYPE_ROOT;
1113 if(isConfigurationNode() && groupId_ !=
"")
return ConfigurationTree::NODE_TYPE_GROUP_TABLE;
1114 if(isConfigurationNode())
return ConfigurationTree::NODE_TYPE_TABLE;
1115 if(isGroupLinkNode())
return ConfigurationTree::NODE_TYPE_GROUP_LINK;
1116 if(isLinkNode())
return ConfigurationTree::NODE_TYPE_UID_LINK;
1117 if(isValueNode())
return ConfigurationTree::NODE_TYPE_VALUE;
1118 return ConfigurationTree::NODE_TYPE_UID;
1124 bool ConfigurationTree::isGroupLinkNode(
void)
const
1126 return (isLinkNode() && groupId_ !=
"");
1132 bool ConfigurationTree::isUIDLinkNode(
void)
const
1134 return (isLinkNode() && groupId_ ==
"");
1140 bool ConfigurationTree::isUIDNode(
void)
const
1142 return (row_ != ConfigurationView::INVALID && col_ == ConfigurationView::INVALID);
1162 std::vector<ConfigurationTree::RecordField> ConfigurationTree::getCommonFields(
1163 const std::vector<std::string /*uid*/> &recordList,
1164 const std::vector<std::string /*relative-path*/> &fieldAcceptList,
1165 const std::vector<std::string /*relative-path*/> &fieldRejectList,
1166 unsigned int depth)
const
1169 if(!isRootNode() && !isConfigurationNode())
1171 __SS__ <<
"Can only get getCommonFields from a root or table node! " <<
1172 "The node type is " << getNodeType() << std::endl;
1173 __COUT__ <<
"\n" << ss.str() << std::endl;
1174 throw std::runtime_error(ss.str());
1177 std::vector<ConfigurationTree::RecordField> fieldCandidateList;
1178 std::vector<int> fieldCount;
1218 for(
unsigned int i=0;i<recordList.size();++i)
1222 auto recordChildren = getNode(recordList[i]).getChildren();
1223 for(
const auto &fieldNode : recordChildren)
1227 if(fieldNode.second.isValueNode())
1230 if(fieldNode.second.getColumnInfo().getType() ==
1231 ViewColumnInfo::TYPE_AUTHOR ||
1232 fieldNode.second.getColumnInfo().getType() ==
1233 ViewColumnInfo::TYPE_TIMESTAMP)
1240 found = fieldAcceptList.size()?
false:
true;
1241 for(
const auto &fieldFilter : fieldAcceptList)
1242 if(StringMacros::wildCardMatch(
1243 fieldFilter,fieldNode.first))
1282 for(
const auto &fieldFilter : fieldRejectList)
1283 if(StringMacros::wildCardMatch(
1284 fieldFilter,fieldNode.first))
1323 fieldCandidateList.push_back(
1325 fieldNode.second.getConfigurationName(),
1329 &fieldNode.second.getColumnInfo()
1331 fieldCount.push_back(-1);
1337 else if(depth > 0 &&
1338 fieldNode.second.isUIDLinkNode() &&
1339 !fieldNode.second.isDisconnected())
1342 fieldNode.second.recursiveGetCommonFields(
1348 fieldNode.first +
"/",
1361 for(
unsigned int i=0;i<fieldCandidateList.size();++i)
1366 if(fieldCount[i] != -1 &&
1367 fieldCount[i] != (
int)recordList.size())
1372 fieldCount.erase(fieldCount.begin() + i);
1373 fieldCandidateList.erase(fieldCandidateList.begin() + i);
1382 return fieldCandidateList;
1390 std::set<std::string > ConfigurationTree::getUniqueValuesForField(
1391 const std::vector<std::string /*relative-path*/> &recordList,
1392 const std::string &fieldName)
const
1395 if(!isConfigurationNode())
1397 __SS__ <<
"Can only get getCommonFields from a table node! " <<
1398 "The node type is " << getNodeType() << std::endl;
1399 __COUT__ <<
"\n" << ss.str() << std::endl;
1400 throw std::runtime_error(ss.str());
1403 std::set<std::string > uniqueValues;
1410 for(
unsigned int i=0;i<recordList.size();++i)
1412 __COUT__ <<
"Checking " << recordList[i] << std::endl;
1420 uniqueValues.emplace(getNode(recordList[i]).getNode(fieldName).getValueAsString(
true));
1423 return uniqueValues;
1429 void ConfigurationTree::recursiveGetCommonFields(
1430 std::vector<ConfigurationTree::RecordField> &fieldCandidateList,
1431 std::vector<int> &fieldCount,
1432 const std::vector<std::string /*relative-path*/> &fieldAcceptList,
1433 const std::vector<std::string /*relative-path*/> &fieldRejectList,
1435 const std::string &relativePathBase,
1462 auto tableName = getConfigurationName();
1463 auto uid = getUIDAsString();
1466 auto recordChildren = getChildren();
1467 for(
const auto &fieldNode : recordChildren)
1469 if(fieldNode.second.isValueNode())
1472 if(fieldNode.second.getColumnInfo().getType() ==
1473 ViewColumnInfo::TYPE_AUTHOR ||
1474 fieldNode.second.getColumnInfo().getType() ==
1475 ViewColumnInfo::TYPE_TIMESTAMP)
1482 found = fieldAcceptList.size()?
false:
true;
1483 for(
const auto &fieldFilter : fieldAcceptList)
1484 if(StringMacros::wildCardMatch(
1485 fieldFilter,fieldNode.first))
1525 for(
const auto &fieldFilter : fieldRejectList)
1526 if(StringMacros::wildCardMatch(
1527 fieldFilter,fieldNode.first))
1568 fieldCandidateList.push_back(
1574 &fieldNode.second.getColumnInfo()
1576 fieldCount.push_back(1);
1583 for(j=0;j<fieldCandidateList.size();++j)
1585 if((relativePathBase + fieldNode.first) ==
1586 (fieldCandidateList[j].relativePath_ +
1587 fieldCandidateList[j].columnName_))
1598 else if(depth > 0 &&
1599 fieldNode.second.isUIDLinkNode() &&
1600 !fieldNode.second.isDisconnected())
1603 fieldNode.second.recursiveGetCommonFields(
1609 (relativePathBase + fieldNode.first) +
"/",
1620 std::vector<std::pair<std::string,ConfigurationTree> > ConfigurationTree::getChildren(
1621 std::map<std::string /*relative-path*/, std::string /*value*/> filterMap,
1622 bool byPriority)
const
1624 std::vector<std::pair<std::string,ConfigurationTree> > retVector;
1628 bool filtering = filterMap.size();
1630 std::string fieldValue;
1632 std::vector<std::string> childrenNames = getChildrenNames(byPriority);
1633 for(
auto &childName : childrenNames)
1643 for(
const auto &filterPair:filterMap)
1645 std::string filterPath = childName +
"/" + filterPair.first;
1650 std::istringstream f(filterPair.second);
1654 while (getline(f, fieldValue,
','))
1663 __COUT__ <<
"\t\tCheck: " << filterPair.first <<
1664 " == " << fieldValue <<
" ??? " <<
1665 this->getNode(filterPath).getValueAsString(
true) <<
1668 if(StringMacros::wildCardMatch(
1669 StringMacros::decodeURIComponent(fieldValue),
1670 this->getNode(filterPath).getValueAsString(
true) ))
1688 __SS__ <<
"Failed to access filter path '" <<
1689 filterPath <<
"' - aborting." << std::endl;
1690 __COUT_ERR__ <<
"\n" << ss.str();
1691 throw std::runtime_error(ss.str());
1699 __COUT__ <<
"\tChild accepted: " << childName << std::endl;
1702 retVector.push_back(std::pair<std::string,ConfigurationTree>(childName,
1703 this->getNode(childName,
true)));
1748 std::map<std::string,ConfigurationTree> ConfigurationTree::getChildrenMap(
void)
const
1750 std::map<std::string,ConfigurationTree> retMap;
1754 std::vector<std::string> childrenNames = getChildrenNames();
1755 for(
auto& childName : childrenNames)
1758 retMap.insert(std::pair<std::string,ConfigurationTree>(childName, this->getNode(childName)));
1766 bool ConfigurationTree::isRootNode(
void)
const
1768 return (!configuration_);
1772 bool ConfigurationTree::isConfigurationNode(
void)
const
1774 return (configuration_ &&
1775 row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID);
1781 std::vector<std::string> ConfigurationTree::getChildrenNames(
bool byPriority)
const
1783 std::vector<std::string > retVector;
1787 __SS__ <<
"Can not get children names of '" <<
1788 getValueAsString() <<
1789 "' with null configuration view pointer!" << std::endl;
1790 if(isLinkNode() && isDisconnected())
1791 ss <<
" This node is a disconnected link to " <<
1792 getDisconnectedTableName() << std::endl;
1794 throw std::runtime_error(ss.str());
1797 if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
1806 std::map<uint64_t , std::vector<
unsigned int > > orderedByPriority;
1807 std::vector<std::string > retPrioritySet;
1809 unsigned int col = configView_->getColPriority();
1810 uint64_t tmpPriority;
1812 for(
unsigned int r = 0; r<configView_->getNumberOfRows(); ++r)
1813 if(groupId_ ==
"" ||
1814 configView_->isEntryInGroup(r,childLinkIndex_,groupId_))
1816 configView_->getValue(tmpPriority,r,col);
1818 orderedByPriority[tmpPriority?tmpPriority:100].push_back(r);
1824 for (
const auto& priorityChildRowVector : orderedByPriority)
1825 for (
const auto& priorityChildRow : priorityChildRowVector.second)
1826 retVector.push_back(configView_->getDataView()[priorityChildRow][configView_->getColUID()]);
1828 __COUT__ <<
"Returning priority children list." << __E__;
1831 catch(std::runtime_error& e)
1833 __COUT_WARN__ <<
"Error identifying priority. Assuming all children have equal priority (Error: " <<
1840 for(
unsigned int r = 0; r<configView_->getNumberOfRows(); ++r)
1841 if(groupId_ ==
"" ||
1842 configView_->isEntryInGroup(r,childLinkIndex_,groupId_))
1845 retVector.push_back(configView_->getDataView()[r][configView_->getColUID()]);
1848 else if(row_ == ConfigurationView::INVALID)
1850 __SS__ <<
"Malformed ConfigurationTree" << std::endl;
1851 __COUT_ERR__ << ss.str();
1852 throw std::runtime_error(ss.str());
1854 else if(col_ == ConfigurationView::INVALID)
1859 for(
unsigned int c = 0; c<configView_->getNumberOfColumns(); ++c)
1860 if(c == configView_->getColUID() ||
1861 configView_->getColumnInfo(c).isChildLinkGroupID() ||
1862 configView_->getColumnInfo(c).isChildLinkUID())
1865 retVector.push_back(configView_->getColumnInfo(c).getName());
1870 __SS__ <<
"\n\nError occurred looking for children of nodeName=" << getValueName() <<
"\n\n" <<
1871 "Invalid depth! getChildrenValues() called from a value point in the Configuration Tree." << std::endl;
1872 __COUT_ERR__ << ss.str();
1873 throw std::runtime_error(ss.str());
1891 __SS__ <<
"Invalid node for get value." << std::endl;
1892 __COUT__ << ss.str();
1893 throw std::runtime_error(ss.str());
1896 std::string valueString = configView_->getValueAsString(row_,col_,
true );
1898 if(valueString.size() && valueString[0] ==
'/')
1904 __COUT__ <<
"Found a valid tree path in value!" << std::endl;
1909 __SS__ <<
"Invalid tree path." << std::endl;
1911 throw std::runtime_error(ss.str());
1917 __SS__ <<
"Invalid value string '" << valueString <<
1918 "' - must start with a '/' character." << std::endl;
1919 throw std::runtime_error(ss.str());