1 #include "otsdaq-core/ConfigurationInterface/ConfigurationTree.h"
2 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationBase.h"
4 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
13 #define __MF_SUBJECT__ "ConfigurationTree"
15 const std::string ConfigurationTree::DISCONNECTED_VALUE =
"X";
16 const std::string ConfigurationTree::VALUE_TYPE_DISCONNECTED =
"Disconnected";
17 const std::string ConfigurationTree::VALUE_TYPE_NODE =
"Node";
20 ConfigurationTree::ConfigurationTree()
24 linkParentConfig_ (0),
29 disconnectedTargetName_ (
""),
30 disconnectedLinkID_ (
""),
54 ConfigurationTree::ConfigurationTree(
57 const std::string& groupId,
59 const std::string& linkColName,
60 const std::string& linkColValue,
61 const unsigned int linkBackRow,
62 const unsigned int linkBackCol,
63 const std::string& disconnectedTargetName,
64 const std::string& disconnectedLinkID,
65 const std::string& childLinkIndex,
66 const unsigned int row,
67 const unsigned int col)
68 : configMgr_ (configMgr),
69 configuration_ (config),
71 linkParentConfig_ (linkParentConfig),
72 linkColName_ (linkColName),
73 linkColValue_ (linkColValue),
74 linkBackRow_ (linkBackRow),
75 linkBackCol_ (linkBackCol),
76 disconnectedTargetName_ (disconnectedTargetName),
77 disconnectedLinkID_ (disconnectedLinkID),
78 childLinkIndex_ (childLinkIndex),
88 ss << __COUT_HDR_FL__ <<
"Invalid empty pointer given to tree!\n" <<
89 "\n\tconfigMgr_=" << configMgr_ <<
90 "\n\tconfiguration_=" << configuration_ <<
91 "\n\tconfigView_=" << configView_ <<
93 __COUT__ <<
"\n" << ss.str();
94 throw std::runtime_error(ss.str());
98 configView_ = &(configuration_->getView());
102 configView_->getColumnInfo(configView_->getColUID()).getType() != ViewColumnInfo::TYPE_UID)
104 __SS__ <<
"Missing UID column (must column of type " << ViewColumnInfo::TYPE_UID <<
105 ") in config view : " << configView_->getTableName() << std::endl;
106 __COUT__ <<
"\n" << ss.str();
107 throw std::runtime_error(ss.str());
113 ConfigurationTree::~ConfigurationTree(
void)
124 void ConfigurationTree::print(
const unsigned int &depth, std::ostream &out)
const
126 recursivePrint(*
this,depth,out,
"\t");
130 void ConfigurationTree::recursivePrint(
const ConfigurationTree &t,
unsigned int depth, std::ostream &out, std::string space)
133 out << space << t.getValueName() <<
" :\t" << t.getValueAsString() << std::endl;
138 out << space << t.getValueName();
139 if(t.isDisconnected())
141 out <<
" :\t" << t.getValueAsString() << std::endl;
145 (t.isGroupLinkNode()?
"Group":
"U") <<
146 "ID=" << t.getValueAsString() <<
150 out << space << t.getValueAsString() <<
" : " << std::endl;
156 auto C = t.getChildren();
158 out << space <<
"{" << std::endl;
160 recursivePrint(c.second,depth-1,out,space +
" ");
162 out << space <<
"}" << std::endl;
172 void ConfigurationTree::getValue(std::string& value)
const
176 if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID)
183 __COUT__ <<
"Success following path to tree node!" << std::endl;
190 value = configView_->validateValueForColumn(
191 valueAsTreeNode.getValueAsString(),col_);
194 __COUT__ <<
"Successful value!" << std::endl;
208 configView_->getValue(value,row_,col_);
210 else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
212 if(isLinkNode() && isDisconnected())
213 value = (groupId_ ==
"") ? getValueName():groupId_;
215 value = (groupId_ ==
"") ? configuration_->getConfigurationName():groupId_;
217 else if(row_ == ConfigurationView::INVALID)
219 __SS__ <<
"Malformed ConfigurationTree" << std::endl;
220 __COUT_ERR__ << ss.str();
221 throw std::runtime_error(ss.str());
223 else if(col_ == ConfigurationView::INVALID)
224 configView_->getValue(value,row_,configView_->getColUID());
227 __SS__ <<
"Impossible." << std::endl;
228 __COUT_ERR__ << ss.str();
229 throw std::runtime_error(ss.str());
246 std::string ConfigurationTree::getValue()
const
249 ConfigurationTree::getValue(value);
256 std::string ConfigurationTree::getEscapedValue()
const
258 if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID)
259 return configView_->getEscapedValueAsString(row_,col_);
261 __SS__ <<
"Can not get escaped value except from a value node!" <<
262 " This node is type '" << getNodeType() <<
"." << std::endl;
263 __COUT_ERR__ <<
"\n" << ss.str();
264 throw std::runtime_error(ss.str());
269 const std::string& ConfigurationTree::getConfigurationName(
void)
const
273 __SS__ <<
"Can not get configuration name of node with no configuration pointer!" << std::endl;
274 throw std::runtime_error(ss.str());
276 return configuration_->getConfigurationName();
283 const std::string& ConfigurationTree::getFieldConfigurationName(
void)
const
288 if(!linkParentConfig_)
290 __SS__ <<
"Can not get configuration name of link node field with no parent configuration pointer!" << std::endl;
291 throw std::runtime_error(ss.str());
293 return linkParentConfig_->getConfigurationName();
296 return getConfigurationName();
301 const std::string& ConfigurationTree::getDisconnectedTableName(
void)
const
303 if(isLinkNode() && isDisconnected())
return disconnectedTargetName_;
305 __SS__ <<
"Can not get disconnected target name of node unless it is a disconnected link node!" << std::endl;
306 throw std::runtime_error(ss.str());
311 const std::string& ConfigurationTree::getDisconnectedLinkID(
void)
const
313 if(isLinkNode() && isDisconnected())
return disconnectedLinkID_;
315 __SS__ <<
"Can not get disconnected target name of node unless it is a disconnected link node!" << std::endl;
316 throw std::runtime_error(ss.str());
325 __SS__ <<
"Can not get configuration version of node with no config view pointer!" << std::endl;
326 throw std::runtime_error(ss.str());
328 return configView_->getVersion();
333 const time_t& ConfigurationTree::getConfigurationCreationTime(
void)
const
337 __SS__ <<
"Can not get configuration creation time of node with no config view pointer!" << std::endl;
338 throw std::runtime_error(ss.str());
340 return configView_->getCreationTime();
348 std::vector<std::string> ConfigurationTree::getFixedChoices(
void)
const
350 if(getValueType() != ViewColumnInfo::TYPE_FIXED_CHOICE_DATA &&
351 getValueType() != ViewColumnInfo::TYPE_BITMAP_DATA &&
354 __SS__ <<
"Can not get fixed choices of node with value type of '" <<
355 getValueType() <<
".' Node must be a link or a value node with type '" <<
356 ViewColumnInfo::TYPE_BITMAP_DATA <<
"' or '" <<
357 ViewColumnInfo::TYPE_FIXED_CHOICE_DATA <<
".'" << std::endl;
358 throw std::runtime_error(ss.str());
361 std::vector<std::string> retVec;
365 if(!linkParentConfig_)
367 __SS__ <<
"Can not get fixed choices of node with no parent config view pointer!" << std::endl;
368 throw std::runtime_error(ss.str());
378 int c = parentView->findCol(linkColName_);
380 std::pair<
unsigned int ,
unsigned int > linkPair;
382 parentView->getChildLink(c, isGroupLink, linkPair);
385 std::vector<std::string> choices = parentView->getColumnInfo(c).getDataChoices();
386 for(
const auto &choice:choices)
387 retVec.push_back(choice);
394 __SS__ <<
"Can not get fixed choices of node with no config view pointer!" << std::endl;
395 throw std::runtime_error(ss.str());
399 retVec.push_back(configView_->getColumnInfo(col_).getDefaultValue());
400 std::vector<std::string> choices = configView_->getColumnInfo(col_).getDataChoices();
401 for(
const auto &choice:choices)
402 retVec.push_back(choice);
415 const std::string& ConfigurationTree::getValueAsString(
bool returnLinkTableValue)
const
419 if(returnLinkTableValue)
420 return linkColValue_;
421 else if(isDisconnected())
422 return ConfigurationTree::DISCONNECTED_VALUE;
423 else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
424 return (groupId_ ==
"")?configuration_->getConfigurationName():groupId_;
425 else if(col_ == ConfigurationView::INVALID)
426 return configView_->getDataView()[row_][configView_->getColUID()];
429 __SS__ <<
"Impossible Link." << std::endl;
430 __COUT_ERR__ << ss.str();
431 throw std::runtime_error(ss.str());
434 else if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID)
435 return configView_->getDataView()[row_][col_];
436 else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
437 return (groupId_ ==
"")?configuration_->getConfigurationName():groupId_;
438 else if(row_ == ConfigurationView::INVALID)
440 __SS__ <<
"Malformed ConfigurationTree" << std::endl;
441 __COUT_ERR__ << ss.str();
442 throw std::runtime_error(ss.str());
444 else if(col_ == ConfigurationView::INVALID)
445 return configView_->getDataView()[row_][configView_->getColUID()];
448 __SS__ <<
"Impossible." << std::endl;
449 __COUT_ERR__ << ss.str();
450 throw std::runtime_error(ss.str());
458 const std::string& ConfigurationTree::getUIDAsString(
void)
const
460 if(isValueNode() || isUIDLinkNode())
461 return configView_->getDataView()[row_][configView_->getColUID()];
464 __SS__ <<
"Can not get UID of node with type '" <<
465 getNodeType() <<
".' Node type must be '" <<
466 ConfigurationTree::NODE_TYPE_VALUE <<
"' or '" <<
467 ConfigurationTree::NODE_TYPE_UID_LINK <<
".'" << std::endl;
468 throw std::runtime_error(ss.str());
475 const std::string& ConfigurationTree::getValueDataType(
void)
const
478 return configView_->getColumnInfo(col_).getDataType();
480 return ViewColumnInfo::DATATYPE_STRING;
486 bool ConfigurationTree::isDefaultValue(
void)
const
488 if(!isValueNode())
return false;
490 if(getValueDataType() == ViewColumnInfo::DATATYPE_STRING)
492 if(getValueType() == ViewColumnInfo::TYPE_ON_OFF ||
493 getValueType() == ViewColumnInfo::TYPE_TRUE_FALSE ||
494 getValueType() == ViewColumnInfo::TYPE_YES_NO)
495 return getValueAsString() == ViewColumnInfo::DATATYPE_BOOL_DEFAULT;
496 else if(getValueType() == ViewColumnInfo::TYPE_COMMENT)
497 return getValueAsString() == ViewColumnInfo::DATATYPE_COMMENT_DEFAULT ||
498 getValueAsString() ==
"";
500 return getValueAsString() == ViewColumnInfo::DATATYPE_STRING_DEFAULT;
502 else if(getValueDataType() == ViewColumnInfo::DATATYPE_NUMBER)
503 return getValueAsString() == ViewColumnInfo::DATATYPE_NUMBER_DEFAULT;
504 else if(getValueDataType() == ViewColumnInfo::DATATYPE_TIME)
505 return getValueAsString() == ViewColumnInfo::DATATYPE_TIME_DEFAULT;
513 const std::string& ConfigurationTree::getValueType(
void)
const
516 return configView_->getColumnInfo(col_).getType();
517 else if(isLinkNode() && isDisconnected())
518 return ConfigurationTree::VALUE_TYPE_DISCONNECTED;
520 return ConfigurationTree::VALUE_TYPE_NODE;
526 const ViewColumnInfo& ConfigurationTree::getColumnInfo(
void)
const
529 return configView_->getColumnInfo(col_);
532 __SS__ <<
"Can only get column info from a value node! " <<
533 "The node type is " << getNodeType() << std::endl;
534 __COUT__ <<
"\n" << ss.str() << std::endl;
535 throw std::runtime_error(ss.str());
542 const unsigned int& ConfigurationTree::getRow(
void)
const
549 const unsigned int& ConfigurationTree::getColumn(
void)
const
557 const unsigned int& ConfigurationTree::getFieldRow(
void)
const
571 const unsigned int& ConfigurationTree::getFieldColumn(
void)
const
584 const std::string& ConfigurationTree::getChildLinkIndex(
void)
const
588 __SS__ <<
"Can only get link ID from a link! " <<
589 "The node type is " << getNodeType() << std::endl;
590 __COUT__ <<
"\n" << ss.str() << std::endl;
591 throw std::runtime_error(ss.str());
593 return childLinkIndex_;
599 const std::string& ConfigurationTree::getValueName(
void)
const
602 return configView_->getColumnInfo(col_).getName();
603 else if(isLinkNode())
607 __SS__ <<
"Can only get value name of a value node!" << std::endl;
608 __COUT__ <<
"\n" << ss.str() << std::endl;
609 throw std::runtime_error(ss.str());
618 const std::string& childPath,
bool doNotThrowOnBrokenUIDLinks)
622 if(childPath.length() <= 1)
624 return tree.getNode(childPath,doNotThrowOnBrokenUIDLinks);
661 bool doNotThrowOnBrokenUIDLinks)
const
667 if(nodeString.length() < 1)
669 __SS__ <<
"Invalid empty node name! Looking for child node from node '" <<
670 getValue() <<
"'..." << std::endl;
671 __COUT_ERR__ << ss.str();
672 throw std::runtime_error(ss.str());
675 bool startingSlash = nodeString[0] ==
'/';
677 std::string nodeName = nodeString.substr(startingSlash?1:0, nodeString.find(
'/',1)-(startingSlash?1:0));
680 std::string childPath = nodeString.substr(nodeName.length() + (startingSlash?1:0));
694 configMgr_->getNode(nodeName),
695 childPath, doNotThrowOnBrokenUIDLinks);
697 else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
703 __SS__ <<
"Missing configView pointer! Likely attempting to access a child node through a disconnected link node." << std::endl;
704 __COUT_ERR__ <<
"\n" << ss.str();
705 throw std::runtime_error(ss.str());
716 ConfigurationView::INVALID , ConfigurationView::INVALID ,
722 configView_->findRow(configView_->getColUID(),nodeName)
723 : configView_->findRowInGroup(configView_->getColUID(),
724 nodeName,groupId_,childLinkIndex_) ),
725 childPath, doNotThrowOnBrokenUIDLinks);
727 else if(row_ == ConfigurationView::INVALID)
729 __SS__ <<
"Malformed ConfigurationTree" << std::endl;
730 __COUT_ERR__ <<
"\n" << ss.str();
731 throw std::runtime_error(ss.str());
733 else if(col_ == ConfigurationView::INVALID)
747 __SS__ <<
"Missing configView pointer! Likely attempting to access a child node through a disconnected link node." << std::endl;
748 __COUT_ERR__ <<
"\n" << ss.str();
749 throw std::runtime_error(ss.str());
752 unsigned int c = configView_->findCol(nodeName);
753 std::pair<
unsigned int ,
unsigned int > linkPair;
754 bool isGroupLink, isLink;
755 if((isLink = configView_->getChildLink(c, isGroupLink, linkPair)) &&
766 childConfig = configMgr_->getConfigurationByName(configView_->getDataView()[row_][linkPair.first]);
767 childConfig->getView();
769 if(doNotThrowOnBrokenUIDLinks)
771 childConfig->getView().findRow(childConfig->getView().getColUID(),
772 configView_->getDataView()[row_][linkPair.second]);
789 configView_->getDataView()[row_][c],
791 configView_->getDataView()[row_][linkPair.first],
792 configView_->getDataView()[row_][linkPair.second],
793 configView_->getColumnInfo(c).getChildLinkIndex());
803 configView_->getDataView()[row_][c],
807 configView_->getColumnInfo(c).getChildLinkIndex(),
808 childConfig->getView().findRow(childConfig->getView().getColUID(),
809 configView_->getDataView()[row_][linkPair.second])
811 childPath, doNotThrowOnBrokenUIDLinks);
823 childConfig = configMgr_->getConfigurationByName(
824 configView_->getDataView()[row_][linkPair.first]);
825 childConfig->getView();
829 if(configView_->getDataView()[row_][linkPair.first] !=
830 ViewColumnInfo::DATATYPE_LINK_DEFAULT)
831 __COUT_WARN__ <<
"Found disconnected node! Failed link target from nodeName=" <<
832 nodeName <<
" to table:id=" <<
833 configView_->getDataView()[row_][linkPair.first] <<
":" <<
834 configView_->getDataView()[row_][linkPair.second] <<
839 configView_->getDataView()[row_][linkPair.second],
842 configView_->getDataView()[row_][c],
844 configView_->getDataView()[row_][linkPair.first],
845 configView_->getDataView()[row_][linkPair.second],
846 configView_->getColumnInfo(c).getChildLinkIndex()
854 configView_->getDataView()[row_][linkPair.second],
857 configView_->getDataView()[row_][c],
861 configView_->getColumnInfo(c).getChildLinkIndex()
863 childPath, doNotThrowOnBrokenUIDLinks);
874 ConfigurationView::INVALID , ConfigurationView::INVALID ,
881 catch(std::runtime_error &e)
883 __SS__ <<
"\n\nError occurred descending from node '" << getValue() <<
884 "' in table '" << getConfigurationName() <<
885 "' looking for child '" << nodeName <<
"'\n\n" << std::endl;
886 ss <<
"--- Additional error detail: \n\n" << e.what() << std::endl;
887 throw std::runtime_error(ss.str());
891 __SS__ <<
"\n\nError occurred descending from node '" << getValue() <<
892 "' in table '" << getConfigurationName() <<
893 "' looking for child '" << nodeName <<
"'\n\n" << std::endl;
894 throw std::runtime_error(ss.str());
898 __SS__ <<
"\n\nError occurred descending from node '" << getValue() <<
899 "' in table '" << getConfigurationName() <<
900 "' looking for child '" << nodeName <<
"'\n\n" <<
901 "Invalid depth! getNode() called from a value point in the Configuration Tree." << std::endl;
902 throw std::runtime_error(ss.str());
907 ConfigurationTree ConfigurationTree::getBackNode(std::string nodeName,
unsigned int backSteps)
const
909 for(
unsigned int i=0; i<backSteps; i++)
910 nodeName = nodeName.substr(0, nodeName.find_last_of(
'/'));
912 return getNode(nodeName);
916 ConfigurationTree ConfigurationTree::getForwardNode(std::string nodeName,
unsigned int forwardSteps)
const
921 while(s < nodeName.length() && nodeName[s] ==
'/') ++s;
923 for(
unsigned int i=0; i<forwardSteps; i++)
924 s = nodeName.find(
'/',s) + 1;
926 return getNode(nodeName.substr(0,s));
931 bool ConfigurationTree::isValueNode(
void)
const
933 return (row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID);
941 bool ConfigurationTree::isDisconnected(
void)
const
945 __SS__ <<
"\n\nError occurred testing link connection at node with value '" <<
947 "' in table '" << getConfigurationName() <<
948 "'\n\n" << std::endl;
949 ss <<
"This is not a Link node! It is node type '" <<
950 getNodeType() <<
".' Only a Link node can be disconnected." << std::endl;
952 throw std::runtime_error(ss.str());
955 return !configuration_ || !configView_;
961 bool ConfigurationTree::isLinkNode(
void)
const
963 return linkColName_ !=
"";
969 const std::string ConfigurationTree::NODE_TYPE_GROUP_TABLE =
"GroupConfigurationNode";
970 const std::string ConfigurationTree::NODE_TYPE_TABLE =
"ConfigurationNode";
971 const std::string ConfigurationTree::NODE_TYPE_GROUP_LINK =
"GroupLinkNode";
972 const std::string ConfigurationTree::NODE_TYPE_UID_LINK =
"UIDLinkNode";
973 const std::string ConfigurationTree::NODE_TYPE_VALUE =
"ValueNode";
974 const std::string ConfigurationTree::NODE_TYPE_UID =
"UIDNode";
975 const std::string ConfigurationTree::NODE_TYPE_ROOT =
"RootNode";
977 std::string ConfigurationTree::getNodeType(
void)
const
979 if(!configuration_)
return ConfigurationTree::NODE_TYPE_ROOT;
980 if(isConfigurationNode() && groupId_ !=
"")
return ConfigurationTree::NODE_TYPE_GROUP_TABLE;
981 if(isConfigurationNode())
return ConfigurationTree::NODE_TYPE_TABLE;
982 if(isGroupLinkNode())
return ConfigurationTree::NODE_TYPE_GROUP_LINK;
983 if(isLinkNode())
return ConfigurationTree::NODE_TYPE_UID_LINK;
984 if(isValueNode())
return ConfigurationTree::NODE_TYPE_VALUE;
985 return ConfigurationTree::NODE_TYPE_UID;
991 bool ConfigurationTree::isGroupLinkNode(
void)
const
993 return (isLinkNode() && groupId_ !=
"");
999 bool ConfigurationTree::isUIDLinkNode(
void)
const
1001 return (isLinkNode() && groupId_ ==
"");
1007 bool ConfigurationTree::isUIDNode(
void)
const
1009 return (row_ != ConfigurationView::INVALID && col_ == ConfigurationView::INVALID);
1029 std::vector<ConfigurationTree::RecordField> ConfigurationTree::getCommonFields(
1030 const std::vector<std::string /*uid*/> &recordList,
1031 const std::vector<std::string /*relative-path*/> &fieldAcceptList,
1032 const std::vector<std::string /*relative-path*/> &fieldRejectList,
1033 unsigned int depth)
const
1036 if(!isRootNode() && !isConfigurationNode())
1038 __SS__ <<
"Can only get getCommonFields from a root or table node! " <<
1039 "The node type is " << getNodeType() << std::endl;
1040 __COUT__ <<
"\n" << ss.str() << std::endl;
1041 throw std::runtime_error(ss.str());
1044 std::vector<ConfigurationTree::RecordField> fieldCandidateList;
1045 std::vector<int> fieldCount;
1085 for(
unsigned int i=0;i<recordList.size();++i)
1089 auto recordChildren = getNode(recordList[i]).getChildren();
1090 for(
const auto &fieldNode : recordChildren)
1094 if(fieldNode.second.isValueNode())
1097 if(fieldNode.second.getColumnInfo().getType() ==
1098 ViewColumnInfo::TYPE_AUTHOR ||
1099 fieldNode.second.getColumnInfo().getType() ==
1100 ViewColumnInfo::TYPE_TIMESTAMP)
1107 found = fieldAcceptList.size()?
false:
true;
1108 for(
const auto &fieldFilter : fieldAcceptList)
1109 if(ConfigurationTree::wildCardMatch(
1110 fieldFilter,fieldNode.first))
1149 for(
const auto &fieldFilter : fieldRejectList)
1150 if(ConfigurationTree::wildCardMatch(
1151 fieldFilter,fieldNode.first))
1190 fieldCandidateList.push_back(
1192 fieldNode.second.getConfigurationName(),
1196 &fieldNode.second.getColumnInfo()
1198 fieldCount.push_back(-1);
1204 else if(depth > 0 &&
1205 fieldNode.second.isUIDLinkNode() &&
1206 !fieldNode.second.isDisconnected())
1209 fieldNode.second.recursiveGetCommonFields(
1215 fieldNode.first +
"/",
1228 for(
unsigned int i=0;i<fieldCandidateList.size();++i)
1233 if(fieldCount[i] != -1 &&
1234 fieldCount[i] != (
int)recordList.size())
1239 fieldCount.erase(fieldCount.begin() + i);
1240 fieldCandidateList.erase(fieldCandidateList.begin() + i);
1249 return fieldCandidateList;
1257 std::set<std::string > ConfigurationTree::getUniqueValuesForField(
1258 const std::vector<std::string /*relative-path*/> &recordList,
1259 const std::string &fieldName)
const
1262 if(!isConfigurationNode())
1264 __SS__ <<
"Can only get getCommonFields from a table node! " <<
1265 "The node type is " << getNodeType() << std::endl;
1266 __COUT__ <<
"\n" << ss.str() << std::endl;
1267 throw std::runtime_error(ss.str());
1270 std::set<std::string > uniqueValues;
1277 for(
unsigned int i=0;i<recordList.size();++i)
1279 __COUT__ <<
"Checking " << recordList[i] << std::endl;
1287 uniqueValues.emplace(getNode(recordList[i]).getNode(fieldName).getValueAsString(
true));
1290 return uniqueValues;
1296 void ConfigurationTree::recursiveGetCommonFields(
1297 std::vector<ConfigurationTree::RecordField> &fieldCandidateList,
1298 std::vector<int> &fieldCount,
1299 const std::vector<std::string /*relative-path*/> &fieldAcceptList,
1300 const std::vector<std::string /*relative-path*/> &fieldRejectList,
1302 const std::string &relativePathBase,
1329 auto tableName = getConfigurationName();
1330 auto uid = getUIDAsString();
1333 auto recordChildren = getChildren();
1334 for(
const auto &fieldNode : recordChildren)
1336 if(fieldNode.second.isValueNode())
1339 if(fieldNode.second.getColumnInfo().getType() ==
1340 ViewColumnInfo::TYPE_AUTHOR ||
1341 fieldNode.second.getColumnInfo().getType() ==
1342 ViewColumnInfo::TYPE_TIMESTAMP)
1349 found = fieldAcceptList.size()?
false:
true;
1350 for(
const auto &fieldFilter : fieldAcceptList)
1351 if(ConfigurationTree::wildCardMatch(
1352 fieldFilter,fieldNode.first))
1392 for(
const auto &fieldFilter : fieldRejectList)
1393 if(ConfigurationTree::wildCardMatch(
1394 fieldFilter,fieldNode.first))
1435 fieldCandidateList.push_back(
1441 &fieldNode.second.getColumnInfo()
1443 fieldCount.push_back(1);
1450 for(j=0;j<fieldCandidateList.size();++j)
1452 if((relativePathBase + fieldNode.first) ==
1453 (fieldCandidateList[j].relativePath_ +
1454 fieldCandidateList[j].columnName_))
1465 else if(depth > 0 &&
1466 fieldNode.second.isUIDLinkNode() &&
1467 !fieldNode.second.isDisconnected())
1470 fieldNode.second.recursiveGetCommonFields(
1476 (relativePathBase + fieldNode.first) +
"/",
1487 std::vector<std::pair<std::string,ConfigurationTree> > ConfigurationTree::getChildren(
1488 std::map<std::string /*relative-path*/, std::string /*value*/> filterMap)
const
1490 std::vector<std::pair<std::string,ConfigurationTree> > retMap;
1494 bool filtering = filterMap.size();
1496 std::string fieldValue;
1498 std::vector<std::string> childrenNames = getChildrenNames();
1499 for(
auto &childName : childrenNames)
1509 for(
const auto &filterPair:filterMap)
1511 std::string filterPath = childName +
"/" + filterPair.first;
1516 std::istringstream f(filterPair.second);
1520 while (getline(f, fieldValue,
','))
1529 __COUT__ <<
"\t\tCheck: " << filterPair.first <<
1530 " == " << fieldValue <<
" ??? " <<
1531 this->getNode(filterPath).getValueAsString(
true) <<
1534 if(ConfigurationTree::wildCardMatch(
1535 ConfigurationView::decodeURIComponent(fieldValue),
1536 this->getNode(filterPath).getValueAsString(
true) ))
1554 __SS__ <<
"Failed to access filter path '" <<
1555 filterPath <<
"' - aborting." << std::endl;
1556 __COUT_ERR__ <<
"\n" << ss.str();
1557 throw std::runtime_error(ss.str());
1565 __COUT__ <<
"\tChild accepted: " << childName << std::endl;
1568 retMap.push_back(std::pair<std::string,ConfigurationTree>(childName,
1569 this->getNode(childName,
true)));
1580 bool ConfigurationTree::wildCardMatch(
const std::string& needle,
const std::string& haystack)
1587 if(needle.size() == 0)
1590 if(needle[0] ==
'*' &&
1591 needle[needle.size()-1] ==
'*' )
1592 return std::string::npos != haystack.find(needle.substr(1,needle.size()-2));
1594 if(needle[0] ==
'*')
1595 return needle.substr(1) ==
1596 haystack.substr(haystack.size() - (needle.size()-1));
1598 if(needle[needle.size()-1] ==
'*')
1599 return needle.substr(0,needle.size()-1) ==
1600 haystack.substr(0,needle.size()-1);
1603 return needle == haystack;
1614 std::map<std::string,ConfigurationTree> ConfigurationTree::getChildrenMap(
void)
const
1616 std::map<std::string,ConfigurationTree> retMap;
1620 std::vector<std::string> childrenNames = getChildrenNames();
1621 for(
auto& childName : childrenNames)
1624 retMap.insert(std::pair<std::string,ConfigurationTree>(childName, this->getNode(childName)));
1632 bool ConfigurationTree::isRootNode(
void)
const
1634 return (!configuration_);
1638 bool ConfigurationTree::isConfigurationNode(
void)
const
1640 return (configuration_ &&
1641 row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID);
1647 std::vector<std::string> ConfigurationTree::getChildrenNames(
void)
const
1649 std::vector<std::string> retSet;
1653 __SS__ <<
"Can not get children names of '" <<
1654 getValueAsString() <<
1655 "' with null configuration view pointer!" << std::endl;
1656 if(isLinkNode() && isDisconnected())
1657 ss <<
" This node is a disconnected link to " <<
1658 getDisconnectedTableName() << std::endl;
1659 __COUT_ERR__ <<
"\n" << ss.str();
1660 throw std::runtime_error(ss.str());
1663 if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
1668 for(
unsigned int r = 0; r<configView_->getNumberOfRows(); ++r)
1669 if(groupId_ ==
"" ||
1670 configView_->isEntryInGroup(r,childLinkIndex_,groupId_))
1673 retSet.push_back(configView_->getDataView()[r][configView_->getColUID()]);
1675 else if(row_ == ConfigurationView::INVALID)
1677 __SS__ <<
"Malformed ConfigurationTree" << std::endl;
1678 __COUT_ERR__ << ss.str();
1679 throw std::runtime_error(ss.str());
1681 else if(col_ == ConfigurationView::INVALID)
1686 for(
unsigned int c = 0; c<configView_->getNumberOfColumns(); ++c)
1687 if(c == configView_->getColUID() ||
1688 configView_->getColumnInfo(c).isChildLinkGroupID() ||
1689 configView_->getColumnInfo(c).isChildLinkUID())
1692 retSet.push_back(configView_->getColumnInfo(c).getName());
1697 __SS__ <<
"\n\nError occurred looking for children of nodeName=" << getValueName() <<
"\n\n" <<
1698 "Invalid depth! getChildrenValues() called from a value point in the Configuration Tree." << std::endl;
1699 __COUT_ERR__ << ss.str();
1700 throw std::runtime_error(ss.str());
1718 __SS__ <<
"Invalid node for get value." << std::endl;
1719 __COUT__ << ss.str();
1720 throw std::runtime_error(ss.str());
1723 std::string valueString = configView_->getValueAsString(row_,col_,
true );
1725 if(valueString.size() && valueString[0] ==
'/')
1731 __COUT__ <<
"Found a valid tree path in value!" << std::endl;
1736 __SS__ <<
"Invalid tree path." << std::endl;
1738 throw std::runtime_error(ss.str());
1744 __SS__ <<
"Invalid value string '" << valueString <<
1745 "' - must start with a '/' character." << std::endl;
1746 throw std::runtime_error(ss.str());