00001 #include "otsdaq-core/ConfigurationInterface/ConfigurationTree.h"
00002
00003 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
00004 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationBase.h"
00005
00006
00007 #include <typeinfo>
00008
00009
00010 using namespace ots;
00011
00012
00013 #undef __MF_SUBJECT__
00014 #define __MF_SUBJECT__ "ConfigurationTree"
00015
00016 const std::string ConfigurationTree::DISCONNECTED_VALUE = "X";
00017 const std::string ConfigurationTree::VALUE_TYPE_DISCONNECTED = "Disconnected";
00018 const std::string ConfigurationTree::VALUE_TYPE_NODE = "Node";
00019
00020
00021 ConfigurationTree::ConfigurationTree()
00022 : configMgr_ (0),
00023 configuration_ (0),
00024 groupId_ (""),
00025 linkColName_ (""),
00026 linkColValue_ (""),
00027 disconnectedTargetName_ (""),
00028 disconnectedLinkID_ (""),
00029 childLinkIndex_ (""),
00030 row_ (0),
00031 col_ (0),
00032 configView_ (0)
00033 {
00034
00035
00036 }
00037
00038 ConfigurationTree::ConfigurationTree(const ConfigurationManager* const &configMgr, const ConfigurationBase* const &config)
00039 : ConfigurationTree(configMgr, config, "", "", "", "", "" , "", ConfigurationView::INVALID, ConfigurationView::INVALID)
00040 {
00041
00042
00043 }
00044
00045
00046 ConfigurationTree::ConfigurationTree(
00047 const ConfigurationManager* const& configMgr,
00048 const ConfigurationBase* const& config,
00049 const std::string& groupId,
00050 const std::string& linkColName,
00051 const std::string& linkColValue,
00052 const std::string& disconnectedTargetName,
00053 const std::string& disconnectedLinkID,
00054 const std::string& childLinkIndex,
00055 const unsigned int row,
00056 const unsigned int col)
00057 : configMgr_ (configMgr),
00058 configuration_ (config),
00059 groupId_ (groupId),
00060 linkColName_ (linkColName),
00061 linkColValue_ (linkColValue),
00062 disconnectedTargetName_ (disconnectedTargetName),
00063 disconnectedLinkID_ (disconnectedLinkID),
00064 childLinkIndex_ (childLinkIndex),
00065 row_ (row),
00066 col_ (col),
00067 configView_ (0)
00068 {
00069
00070
00071 if(!configMgr_)
00072 {
00073 std::stringstream ss;
00074 ss << __COUT_HDR_FL__ << "Invalid empty pointer given to tree!\n" <<
00075 "\n\tconfigMgr_=" << configMgr_ <<
00076 "\n\tconfiguration_=" << configuration_ <<
00077 "\n\tconfigView_=" << configView_ <<
00078 std::endl;
00079 __MOUT__ << ss.str();
00080 throw std::runtime_error(ss.str());
00081 }
00082
00083 if(configuration_)
00084 configView_ = &(configuration_->getView());
00085
00086
00087 if(configView_ &&
00088 configView_->getColumnInfo(configView_->getColUID()).getType() != ViewColumnInfo::TYPE_UID)
00089 {
00090 __SS__ << "Missing UID column (must column of type " << ViewColumnInfo::TYPE_UID <<
00091 ") in config view : " << configView_->getTableName() << std::endl;
00092 __MOUT__ << ss.str();
00093 throw std::runtime_error(ss.str());
00094 }
00095 }
00096
00097
00098
00099 ConfigurationTree::~ConfigurationTree(void)
00100 {
00101
00102 }
00103
00104
00105
00106
00107
00108
00109
00110 void ConfigurationTree::print(const unsigned int &depth, std::ostream &out) const
00111 {
00112 recursivePrint(*this,depth,out,"\t");
00113 }
00114
00115
00116 void ConfigurationTree::recursivePrint(const ConfigurationTree &t, unsigned int depth, std::ostream &out, std::string space)
00117 {
00118 if(t.isValueNode())
00119 out << space << t.getValueName() << " :\t" << t.getValueAsString() << std::endl;
00120 else
00121 {
00122 if(t.isLinkNode())
00123 {
00124 out << space << t.getValueName();
00125 if(t.isDisconnected())
00126 {
00127 out << " :\t" << t.getValueAsString() << std::endl;
00128 return;
00129 }
00130 out << " (" <<
00131 (t.isGroupLinkNode()?"Group":"U") <<
00132 "ID=" << t.getValueAsString() <<
00133 ") : " << std::endl;
00134 }
00135 else
00136 out << space << t.getValueAsString() << " : " << std::endl;
00137
00138
00139
00140 if(depth >= 1)
00141 {
00142 auto C = t.getChildren();
00143 if(!C.empty())
00144 out << space << "{" << std::endl;
00145 for(auto &c:C)
00146 recursivePrint(c.second,depth-1,out,space + " ");
00147 if(!C.empty())
00148 out << space << "}" << std::endl;
00149 }
00150 }
00151 }
00152
00153
00154
00155
00156 void ConfigurationTree::getValue(std::string& value) const
00157 {
00158
00159
00160 if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID)
00161 configView_->getValue(value,row_,col_);
00162 else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
00163 {
00164 if(isLinkNode() && isDisconnected())
00165 value = (groupId_ == "") ? getValueName():groupId_;
00166 else
00167 value = (groupId_ == "") ? configuration_->getConfigurationName():groupId_;
00168 }
00169 else if(row_ == ConfigurationView::INVALID)
00170 {
00171 __MOUT__ << std::endl;
00172 throw std::runtime_error("Malformed ConfigurationTree");
00173 }
00174 else if(col_ == ConfigurationView::INVALID)
00175 configView_->getValue(value,row_,configView_->getColUID());
00176 else
00177 {
00178 __MOUT__ << std::endl;
00179 throw std::runtime_error("Impossible.");
00180 }
00181
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 std::string ConfigurationTree::getValue() const
00194 {
00195
00196
00197 std::string value = "";
00198 if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID)
00199 configView_->getValue(value,row_,col_);
00200 else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
00201 {
00202 if(isLinkNode() && isDisconnected())
00203 value = (groupId_ == "") ? getValueName():groupId_;
00204 else
00205 value = (groupId_ == "") ? configuration_->getConfigurationName():groupId_;
00206 }
00207 else if(row_ == ConfigurationView::INVALID)
00208 {
00209 __MOUT__ << std::endl;
00210 throw std::runtime_error("Malformed ConfigurationTree");
00211 }
00212 else if(col_ == ConfigurationView::INVALID)
00213 configView_->getValue(value,row_,configView_->getColUID());
00214 else
00215 {
00216 __MOUT__ << std::endl;
00217 throw std::runtime_error("Impossible.");
00218 }
00219 return value;
00220
00221 }
00222
00223
00224
00225
00226 std::string ConfigurationTree::getEscapedValue() const
00227 {
00228 if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID)
00229 return configView_->getEscapedValueAsString(row_,col_);
00230
00231 __SS__ << "Can't get escaped value except from a value node!" <<
00232 " This node is type '" << getNodeType() << "." << std::endl;
00233 __MOUT_ERR__ << "\n" << ss.str();
00234 throw std::runtime_error(ss.str());
00235 }
00236
00237
00238
00239 const std::string& ConfigurationTree::getConfigurationName(void) const
00240 {
00241 if(!configuration_)
00242 {
00243 __SS__ << "Can't get configuration name of node with no configuration pointer!" << std::endl;
00244 throw std::runtime_error(ss.str());
00245 }
00246 return configuration_->getConfigurationName();
00247 }
00248
00249
00250
00251 const std::string& ConfigurationTree::getDisconnectedTableName(void) const
00252 {
00253 if(isLinkNode() && isDisconnected()) return disconnectedTargetName_;
00254
00255 __SS__ << "Can't get disconnected target name of node unless it is a disconnected link node!" << std::endl;
00256 throw std::runtime_error(ss.str());
00257 }
00258
00259
00260
00261 const std::string& ConfigurationTree::getDisconnectedLinkID(void) const
00262 {
00263 if(isLinkNode() && isDisconnected()) return disconnectedLinkID_;
00264
00265 __SS__ << "Can't get disconnected target name of node unless it is a disconnected link node!" << std::endl;
00266 throw std::runtime_error(ss.str());
00267 }
00268
00269
00270
00271 const ConfigurationVersion& ConfigurationTree::getConfigurationVersion(void) const
00272 {
00273 if(!configView_)
00274 {
00275 __SS__ << "Can't get configuration version of node with no config view pointer!" << std::endl;
00276 throw std::runtime_error(ss.str());
00277 }
00278 return configView_->getVersion();
00279 }
00280
00281
00282
00283 const time_t& ConfigurationTree::getConfigurationCreationTime(void) const
00284 {
00285 if(!configView_)
00286 {
00287 __SS__ << "Can't get configuration creation time of node with no config view pointer!" << std::endl;
00288 throw std::runtime_error(ss.str());
00289 }
00290 return configView_->getCreationTime();
00291 }
00292
00293
00294
00295
00296
00297
00298 std::vector<std::string> ConfigurationTree::getFixedChoices(void) const
00299 {
00300 if(!configView_)
00301 {
00302 __SS__ << "Can't get fixed choices of node with no config view pointer!" << std::endl;
00303 throw std::runtime_error(ss.str());
00304 }
00305
00306 if(getValueType() != ViewColumnInfo::TYPE_FIXED_CHOICE_DATA &&
00307 getValueType() != ViewColumnInfo::TYPE_BITMAP_DATA)
00308 {
00309 __SS__ << "Can't get fixed choices of node with value type of '" <<
00310 getValueType() << ".' Value type must be '" <<
00311 ViewColumnInfo::TYPE_BITMAP_DATA << "' or '" <<
00312 ViewColumnInfo::TYPE_FIXED_CHOICE_DATA << ".'" << std::endl;
00313 throw std::runtime_error(ss.str());
00314 }
00315
00316
00317 std::vector<std::string> retVec;
00318 retVec.push_back(configView_->getColumnInfo(col_).getDefaultValue());
00319 std::vector<std::string> choices = configView_->getColumnInfo(col_).getDataChoices();
00320 for(const auto &choice:choices)
00321 retVec.push_back(choice);
00322
00323 return retVec;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 const std::string& ConfigurationTree::getValueAsString(bool returnLinkTableValue) const
00335 {
00336 if(isLinkNode())
00337 {
00338 if(returnLinkTableValue)
00339 return linkColValue_;
00340 else if(isDisconnected())
00341 return ConfigurationTree::DISCONNECTED_VALUE;
00342 else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
00343 return (groupId_ == "")?configuration_->getConfigurationName():groupId_;
00344 else if(col_ == ConfigurationView::INVALID)
00345 return configView_->getDataView()[row_][configView_->getColUID()];
00346 else
00347 {
00348 __MOUT__ << std::endl;
00349 throw std::runtime_error("Impossible Link.");
00350 }
00351 }
00352 else if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID)
00353 return configView_->getDataView()[row_][col_];
00354 else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
00355 return (groupId_ == "")?configuration_->getConfigurationName():groupId_;
00356 else if(row_ == ConfigurationView::INVALID)
00357 {
00358 __MOUT__ << std::endl;
00359 throw std::runtime_error("Malformed ConfigurationTree");
00360 }
00361 else if(col_ == ConfigurationView::INVALID)
00362 return configView_->getDataView()[row_][configView_->getColUID()];
00363 else
00364 {
00365 __MOUT__ << std::endl;
00366 throw std::runtime_error("Impossible.");
00367 }
00368 }
00369
00370
00371
00372
00373
00374 const std::string& ConfigurationTree::getUIDAsString(void) const
00375 {
00376 if(isValueNode() || isUIDLinkNode())
00377 return configView_->getDataView()[row_][configView_->getColUID()];
00378
00379 {
00380 __SS__ << "Can't get UID of node with type '" <<
00381 getNodeType() << ".' Node type must be '" <<
00382 ConfigurationTree::NODE_TYPE_VALUE << "' or '" <<
00383 ConfigurationTree::NODE_TYPE_UID_LINK << ".'" << std::endl;
00384 throw std::runtime_error(ss.str());
00385 }
00386 }
00387
00388
00389
00390
00391 const std::string& ConfigurationTree::getValueDataType(void) const
00392 {
00393 if(isValueNode())
00394 return configView_->getColumnInfo(col_).getDataType();
00395 else
00396 return ViewColumnInfo::DATATYPE_STRING;
00397 }
00398
00399
00400
00401
00402 bool ConfigurationTree::isDefaultValue(void) const
00403 {
00404 if(!isValueNode()) return false;
00405
00406 if(getValueDataType() == ViewColumnInfo::DATATYPE_STRING)
00407 {
00408 if(getValueType() == ViewColumnInfo::TYPE_ON_OFF ||
00409 getValueType() == ViewColumnInfo::TYPE_TRUE_FALSE ||
00410 getValueType() == ViewColumnInfo::TYPE_YES_NO)
00411 return getValueAsString() == ViewColumnInfo::DATATYPE_BOOL_DEFAULT;
00412 else if(getValueType() == ViewColumnInfo::TYPE_COMMENT)
00413 return getValueAsString() == ViewColumnInfo::DATATYPE_COMMENT_DEFAULT ||
00414 getValueAsString() == "";
00415 else
00416 return getValueAsString() == ViewColumnInfo::DATATYPE_STRING_DEFAULT;
00417 }
00418 else if(getValueDataType() == ViewColumnInfo::DATATYPE_NUMBER)
00419 return getValueAsString() == ViewColumnInfo::DATATYPE_NUMBER_DEFAULT;
00420 else if(getValueDataType() == ViewColumnInfo::DATATYPE_TIME)
00421 return getValueAsString() == ViewColumnInfo::DATATYPE_TIME_DEFAULT;
00422 else
00423 return false;
00424 }
00425
00426
00427
00428
00429 const std::string& ConfigurationTree::getValueType(void) const
00430 {
00431 if(isValueNode())
00432 return configView_->getColumnInfo(col_).getType();
00433 else if(isLinkNode() && isDisconnected())
00434 return ConfigurationTree::VALUE_TYPE_DISCONNECTED;
00435 else
00436 return ConfigurationTree::VALUE_TYPE_NODE;
00437 }
00438
00439
00440
00441
00442 const ViewColumnInfo& ConfigurationTree::getColumnInfo(void) const
00443 {
00444 if(isValueNode())
00445 return configView_->getColumnInfo(col_);
00446 else
00447 {
00448 __SS__ << "Can only get column info from a value node! " <<
00449 "The node type is " << getNodeType() << std::endl;
00450 __MOUT__ << "\n" << ss.str() << std::endl;
00451 throw std::runtime_error(ss.str());
00452 }
00453
00454 }
00455
00456
00457
00458 const unsigned int& ConfigurationTree::getRow(void) const
00459 { return row_; }
00460
00461
00462
00463 const unsigned int& ConfigurationTree::getColumn(void) const
00464 { return col_; }
00465
00466
00467
00468 const std::string& ConfigurationTree::getChildLinkIndex(void) const
00469 {
00470 if(!isLinkNode())
00471 {
00472 __SS__ << "Can only get link ID from a link! " <<
00473 "The node type is " << getNodeType() << std::endl;
00474 __MOUT__ << "\n" << ss.str() << std::endl;
00475 throw std::runtime_error(ss.str());
00476 }
00477 return childLinkIndex_;
00478 }
00479
00480
00481
00482
00483 const std::string& ConfigurationTree::getValueName(void) const
00484 {
00485 if(isValueNode())
00486 return configView_->getColumnInfo(col_).getName();
00487 else if(isLinkNode())
00488 return linkColName_;
00489 else
00490 {
00491 __SS__ << "Can only get value name of a value node!" << std::endl;
00492 __MOUT__ << "\n" << ss.str() << std::endl;
00493 throw std::runtime_error(ss.str());
00494 }
00495
00496 }
00497
00498
00499
00500
00501 ConfigurationTree ConfigurationTree::recurse(const ConfigurationTree& tree, const std::string& childPath)
00502 {
00503
00504
00505 if(childPath.length() <= 1)
00506 return tree;
00507 return tree.getNode(childPath);
00508 }
00509
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 ConfigurationTree ConfigurationTree::getNode(const std::string &nodeString,
00544 bool doNotThrowOnBrokenUIDLinks) const
00545 {
00546
00547
00548
00549 if(nodeString.length() < 1) throw std::runtime_error("Invalid node name!");
00550
00551 bool startingSlash = nodeString[0] == '/';
00552
00553 std::string nodeName = nodeString.substr(startingSlash?1:0, nodeString.find('/',1)-(startingSlash?1:0));
00554
00555
00556 std::string childPath = nodeString.substr(nodeName.length() + (startingSlash?1:0));
00557
00558
00559
00560
00561 try
00562 {
00563
00564
00565 if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
00566 {
00567
00568 return recurse(ConfigurationTree(
00569 configMgr_,
00570 configuration_,
00571 "",
00572 "",
00573 "",
00574 "",
00575 "",
00576 "",
00577
00578 (groupId_ == "")?
00579 configView_->findRow(configView_->getColUID(),nodeName)
00580 : configView_->findRowInGroup(configView_->getColUID(),
00581 nodeName,groupId_,childLinkIndex_) ),
00582 childPath);
00583 }
00584 else if(row_ == ConfigurationView::INVALID)
00585 {
00586
00587 throw std::runtime_error("Malformed ConfigurationTree");
00588 }
00589 else if(col_ == ConfigurationView::INVALID)
00590 {
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 unsigned int c = configView_->findCol(nodeName);
00602 std::pair<unsigned int , unsigned int > linkPair;
00603 bool isGroupLink, isLink;
00604 if((isLink = configView_->getChildLink(c, &isGroupLink, &linkPair)) &&
00605 !isGroupLink)
00606 {
00607
00608
00609
00610
00611
00612 const ConfigurationBase* childConfig;
00613 try
00614 {
00615 childConfig = configMgr_->getConfigurationByName(configView_->getDataView()[row_][linkPair.first]);
00616 childConfig->getView();
00617
00618 if(doNotThrowOnBrokenUIDLinks)
00619 {
00620 childConfig->getView().findRow(childConfig->getView().getColUID(),
00621 configView_->getDataView()[row_][linkPair.second]);
00622 }
00623 }
00624 catch(...)
00625 {
00626
00627
00628
00629
00630
00631
00632 return ConfigurationTree(
00633 configMgr_,
00634 0,
00635 "",
00636 nodeName,
00637 configView_->getDataView()[row_][c],
00638 configView_->getDataView()[row_][linkPair.first],
00639 configView_->getDataView()[row_][linkPair.second],
00640 configView_->getColumnInfo(c).getChildLinkIndex());
00641 }
00642
00643 return recurse(
00644 ConfigurationTree(
00645 configMgr_,
00646 childConfig,
00647 "",
00648 nodeName,
00649 configView_->getDataView()[row_][c],
00650 "",
00651 "",
00652 configView_->getColumnInfo(c).getChildLinkIndex(),
00653 childConfig->getView().findRow(childConfig->getView().getColUID(),
00654 configView_->getDataView()[row_][linkPair.second])
00655 ),
00656 childPath);
00657 }
00658 else if(isLink)
00659 {
00660
00661
00662
00663
00664
00665 const ConfigurationBase* childConfig;
00666 try
00667 {
00668 childConfig = configMgr_->getConfigurationByName(
00669 configView_->getDataView()[row_][linkPair.first]);
00670 childConfig->getView();
00671 }
00672 catch(...)
00673 {
00674 if(configView_->getDataView()[row_][linkPair.first] !=
00675 ViewColumnInfo::DATATYPE_LINK_DEFAULT)
00676 __MOUT_WARN__ << "Found disconnected node! Failed link target from nodeName=" <<
00677 nodeName << " to table:id=" <<
00678 configView_->getDataView()[row_][linkPair.first] << ":" <<
00679 configView_->getDataView()[row_][linkPair.second] <<
00680 std::endl;
00681
00682
00683 return ConfigurationTree(configMgr_,0,
00684 configView_->getDataView()[row_][linkPair.second],
00685 nodeName,
00686 configView_->getDataView()[row_][c],
00687 configView_->getDataView()[row_][linkPair.first],
00688 configView_->getDataView()[row_][linkPair.second],
00689 configView_->getColumnInfo(c).getChildLinkIndex()
00690 );
00691 }
00692
00693 return recurse(
00694 ConfigurationTree(
00695 configMgr_,
00696 childConfig,
00697 configView_->getDataView()[row_][linkPair.second],
00698 nodeName,
00699 configView_->getDataView()[row_][c],
00700 "",
00701 "",
00702 configView_->getColumnInfo(c).getChildLinkIndex()
00703 ),
00704 childPath);
00705 }
00706 else
00707 {
00708
00709
00710 return ConfigurationTree(
00711 configMgr_,
00712 configuration_,"","","","","","",
00713 row_,c);
00714 }
00715 }
00716
00717 }
00718 catch(std::runtime_error &e)
00719 {
00720 __SS__ << "\n\nError occurred descending from node '" << getValue() <<
00721 "' looking for child '" << nodeName << "'\n\n" << std::endl;
00722 ss << "--- Additional error detail: \n\n" << e.what() << std::endl;
00723 throw std::runtime_error(ss.str());
00724 }
00725 catch(...)
00726 {
00727 __SS__ << "\n\nError occurred descending from node '" << getValue() <<
00728 "' looking for child '" << nodeName << "'\n\n" << std::endl;
00729 throw std::runtime_error(ss.str());
00730 }
00731
00732
00733 __SS__ << "\n\nError occurred looking for nodeName=" << nodeName << "\n\n" <<
00734 "Invalid depth! getNode() called from a value point in the Configuration Tree." << std::endl;
00735 throw std::runtime_error(ss.str());
00736 }
00737
00738
00739
00740 ConfigurationTree ConfigurationTree::getBackNode(std::string nodeName, unsigned int backSteps) const
00741 {
00742 for(unsigned int i=0; i<backSteps; i++)
00743 nodeName = nodeName.substr(0, nodeName.find_last_of('/'));
00744
00745 return getNode(nodeName);
00746 }
00747
00748
00749
00750
00751 bool ConfigurationTree::isValueNode(void) const
00752 {
00753 return (row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID);
00754 }
00755
00756
00757
00758
00759
00760
00761 bool ConfigurationTree::isDisconnected(void) const
00762 {
00763 if(!isLinkNode())
00764 {
00765 __SS__ << "This is not a Link node! Only a Link node can be disconnected." << std::endl;
00766 __MOUT__ << ss.str();
00767 throw std::runtime_error(ss.str());
00768 }
00769
00770 return !configuration_ || !configView_;
00771 }
00772
00773
00774
00775
00776 bool ConfigurationTree::isLinkNode(void) const
00777 {
00778 return linkColName_ != "";
00779 }
00780
00781
00782
00783
00784 const std::string ConfigurationTree::NODE_TYPE_GROUP_TABLE = "GroupConfigurationNode";
00785 const std::string ConfigurationTree::NODE_TYPE_TABLE = "ConfigurationNode";
00786 const std::string ConfigurationTree::NODE_TYPE_GROUP_LINK = "GroupLinkNode";
00787 const std::string ConfigurationTree::NODE_TYPE_UID_LINK = "UIDLinkNode";
00788 const std::string ConfigurationTree::NODE_TYPE_VALUE = "ValueNode";
00789 const std::string ConfigurationTree::NODE_TYPE_UID = "UIDNode";
00790 std::string ConfigurationTree::getNodeType(void) const
00791 {
00792 if(isConfigurationNode() && groupId_ != "") return ConfigurationTree::NODE_TYPE_GROUP_TABLE;
00793 if(isConfigurationNode()) return ConfigurationTree::NODE_TYPE_TABLE;
00794 if(isGroupLinkNode()) return ConfigurationTree::NODE_TYPE_GROUP_LINK;
00795 if(isLinkNode()) return ConfigurationTree::NODE_TYPE_UID_LINK;
00796 if(isValueNode()) return ConfigurationTree::NODE_TYPE_VALUE;
00797 return ConfigurationTree::NODE_TYPE_UID;
00798 }
00799
00800
00801
00802
00803 bool ConfigurationTree::isGroupLinkNode(void) const
00804 {
00805 return (isLinkNode() && groupId_ != "");
00806 }
00807
00808
00809
00810
00811 bool ConfigurationTree::isUIDLinkNode(void) const
00812 {
00813 return (isLinkNode() && groupId_ == "");
00814 }
00815
00816
00817
00818
00819 bool ConfigurationTree::isUIDNode(void) const
00820 {
00821 return (row_ != ConfigurationView::INVALID && col_ == ConfigurationView::INVALID);
00822 }
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841 std::vector<ConfigurationTree::RecordField> ConfigurationTree::getCommonFields(
00842 const std::vector<std::string /*uid*/> &recordList,
00843 const std::vector<std::string /*relative-path*/> &fieldAcceptList,
00844 const std::vector<std::string /*relative-path*/> &fieldRejectList,
00845 unsigned int depth) const
00846 {
00847
00848 if(!isConfigurationNode())
00849 {
00850 __SS__ << "Can only get getCommonFields from a table node! " <<
00851 "The node type is " << getNodeType() << std::endl;
00852 __MOUT__ << "\n" << ss.str() << std::endl;
00853 throw std::runtime_error(ss.str());
00854 }
00855
00856 std::vector<ConfigurationTree::RecordField> fieldCandidateList;
00857 std::vector<int> fieldCount;
00858
00859 --depth;
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 bool found;
00895 auto tableName = getConfigurationName();
00896
00897 for(unsigned int i=0;i<recordList.size();++i)
00898 {
00899
00900
00901 auto recordChildren = getNode(recordList[i]).getChildren();
00902 for(const auto &fieldNode : recordChildren)
00903 {
00904
00905
00906 if(fieldNode.second.isValueNode())
00907 {
00908
00909 if(fieldNode.second.getColumnInfo().getType() ==
00910 ViewColumnInfo::TYPE_AUTHOR ||
00911 fieldNode.second.getColumnInfo().getType() ==
00912 ViewColumnInfo::TYPE_TIMESTAMP)
00913 continue;
00914
00915
00916 if(!i)
00917 {
00918
00919 found = fieldAcceptList.size()?false:true;
00920 for(const auto &fieldFilter : fieldAcceptList)
00921 if(fieldFilter[0] == '*')
00922 {
00923 if(fieldNode.first ==
00924 fieldFilter.substr(1))
00925 {
00926 found = true;
00927 break;
00928 }
00929 }
00930 else if(fieldFilter.size() &&
00931 fieldFilter[fieldFilter.size()-1] == '*')
00932 {
00933 if(fieldNode.first.substr(0,fieldFilter.size()-1) ==
00934 fieldFilter.substr(0,fieldFilter.size()-1))
00935 {
00936 found = true;
00937 break;
00938 }
00939 }
00940 else
00941 {
00942 if(fieldNode.first == fieldFilter)
00943 {
00944 found = true;
00945 break;
00946 }
00947 }
00948
00949
00950 if(found)
00951 {
00952
00953
00954 found = true;
00955 for(const auto &fieldFilter : fieldRejectList)
00956 if(fieldFilter[0] == '*')
00957 {
00958 if(fieldNode.first ==
00959 fieldFilter.substr(1))
00960 {
00961 found = false;
00962 break;
00963 }
00964 }
00965 else if(fieldFilter.size() &&
00966 fieldFilter[fieldFilter.size()-1] == '*')
00967 {
00968 if(fieldNode.first.substr(0,fieldFilter.size()-1) ==
00969 fieldFilter.substr(0,fieldFilter.size()-1))
00970 {
00971 found = false;
00972 break;
00973 }
00974 }
00975 else
00976 {
00977 if(fieldNode.first == fieldFilter)
00978 {
00979 found = false;
00980 break;
00981 }
00982 }
00983
00984 }
00985
00986
00987 if(found)
00988 {
00989 fieldCandidateList.push_back(
00990 ConfigurationTree::RecordField(
00991 tableName,
00992 recordList[i],
00993 fieldNode.first,
00994 "",
00995 &fieldNode.second.getColumnInfo()
00996 ));
00997 fieldCount.push_back(-1);
00998 }
00999 }
01000
01001
01002 }
01003 else if(depth > 0 &&
01004 fieldNode.second.isUIDLinkNode() &&
01005 !fieldNode.second.isDisconnected())
01006 {
01007
01008 fieldNode.second.recursiveGetCommonFields(
01009 fieldCandidateList,
01010 fieldCount,
01011 fieldAcceptList,
01012 fieldRejectList,
01013 depth,
01014 fieldNode.first + "/",
01015 !i
01016 );
01017 }
01018 }
01019
01020 }
01021
01022
01023
01024
01025
01026
01027 for(unsigned int i=0;i<fieldCandidateList.size();++i)
01028 {
01029
01030
01031
01032 if(fieldCount[i] != -1 &&
01033 fieldCount[i] != (int)recordList.size())
01034 {
01035
01036
01037
01038 fieldCount.erase(fieldCount.begin() + i);
01039 fieldCandidateList.erase(fieldCandidateList.begin() + i);
01040 --i;
01041 }
01042 }
01043
01044 for(unsigned int i=0;i<fieldCandidateList.size();++i)
01045 __MOUT__ << "Final " << fieldCandidateList[i].relativePath_ <<
01046 fieldCandidateList[i].columnName_ << std::endl;
01047
01048 return fieldCandidateList;
01049 }
01050
01051
01052
01053
01054
01055
01056 std::set<std::string > ConfigurationTree::getUniqueValuesForField(
01057 const std::vector<std::string /*relative-path*/> &recordList,
01058 const std::string &fieldName) const
01059 {
01060
01061 if(!isConfigurationNode())
01062 {
01063 __SS__ << "Can only get getCommonFields from a table node! " <<
01064 "The node type is " << getNodeType() << std::endl;
01065 __MOUT__ << "\n" << ss.str() << std::endl;
01066 throw std::runtime_error(ss.str());
01067 }
01068
01069 std::set<std::string > uniqueValues;
01070
01071
01072
01073
01074
01075
01076 for(unsigned int i=0;i<recordList.size();++i)
01077 {
01078 __MOUT__ << "Checking " << recordList[i] << std::endl;
01079
01080
01081
01082
01083
01084
01085
01086 uniqueValues.emplace(getNode(recordList[i]).getNode(fieldName).getValueAsString(true));
01087 }
01088
01089 return uniqueValues;
01090 }
01091
01092
01093
01094
01095 void ConfigurationTree::recursiveGetCommonFields(
01096 std::vector<ConfigurationTree::RecordField> &fieldCandidateList,
01097 std::vector<int> &fieldCount,
01098 const std::vector<std::string /*relative-path*/> &fieldAcceptList,
01099 const std::vector<std::string /*relative-path*/> &fieldRejectList,
01100 unsigned int depth,
01101 const std::string &relativePathBase,
01102 bool inFirstRecord
01103 ) const
01104 {
01105 --depth;
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127 bool found;
01128 auto tableName = getConfigurationName();
01129 auto uid = getUIDAsString();
01130 unsigned int j;
01131
01132 auto recordChildren = getChildren();
01133 for(const auto &fieldNode : recordChildren)
01134 {
01135 if(fieldNode.second.isValueNode())
01136 {
01137
01138 if(fieldNode.second.getColumnInfo().getType() ==
01139 ViewColumnInfo::TYPE_AUTHOR ||
01140 fieldNode.second.getColumnInfo().getType() ==
01141 ViewColumnInfo::TYPE_TIMESTAMP)
01142 continue;
01143
01144
01145 if(inFirstRecord)
01146 {
01147
01148 found = fieldAcceptList.size()?false:true;
01149 for(const auto &fieldFilter : fieldAcceptList)
01150 if(fieldFilter[0] == '*')
01151 {
01152 if(fieldNode.first ==
01153 fieldFilter.substr(1))
01154 {
01155 found = true;
01156 break;
01157 }
01158 }
01159 else if(fieldFilter.size() &&
01160 fieldFilter[fieldFilter.size()-1] == '*')
01161 {
01162 if((relativePathBase + fieldNode.first).substr(
01163 0,fieldFilter.size()-1) ==
01164 fieldFilter.substr(0,fieldFilter.size()-1))
01165 {
01166 found = true;
01167 break;
01168 }
01169 }
01170 else
01171 {
01172 if((relativePathBase + fieldNode.first) ==
01173 fieldFilter)
01174 {
01175 found = true;
01176 break;
01177 }
01178 }
01179
01180 if(found)
01181 {
01182
01183
01184 found = true;
01185 for(const auto &fieldFilter : fieldRejectList)
01186 if(fieldFilter[0] == '*')
01187 {
01188 if(fieldNode.first ==
01189 fieldFilter.substr(1))
01190 {
01191 found = false;
01192 break;
01193 }
01194 }
01195 else if(fieldFilter.size() &&
01196 fieldFilter[fieldFilter.size()-1] == '*')
01197 {
01198 if((relativePathBase + fieldNode.first).substr(
01199 0,fieldFilter.size()-1) ==
01200 fieldFilter.substr(0,fieldFilter.size()-1))
01201 {
01202 found = false;
01203 break;
01204 }
01205 }
01206 else
01207 {
01208 if((relativePathBase + fieldNode.first) ==
01209 fieldFilter)
01210 {
01211 found = false;
01212 break;
01213 }
01214 }
01215 }
01216
01217
01218 if(found)
01219 {
01220
01221
01222 fieldCandidateList.push_back(
01223 ConfigurationTree::RecordField(
01224 tableName,
01225 uid,
01226 fieldNode.first,
01227 relativePathBase,
01228 &fieldNode.second.getColumnInfo()
01229 ));
01230 fieldCount.push_back(1);
01231 }
01232 }
01233 else
01234 {
01235
01236
01237 for(j=0;j<fieldCandidateList.size();++j)
01238 {
01239 if((relativePathBase + fieldNode.first) ==
01240 (fieldCandidateList[j].relativePath_ +
01241 fieldCandidateList[j].columnName_))
01242 {
01243
01244
01245
01246 ++fieldCount[j];
01247 break;
01248 }
01249 }
01250 }
01251 }
01252 else if(depth > 0 &&
01253 fieldNode.second.isUIDLinkNode() &&
01254 !fieldNode.second.isDisconnected())
01255 {
01256
01257 fieldNode.second.recursiveGetCommonFields(
01258 fieldCandidateList,
01259 fieldCount,
01260 fieldAcceptList,
01261 fieldRejectList,
01262 depth,
01263 (relativePathBase + fieldNode.first) + "/",
01264 inFirstRecord
01265 );
01266 }
01267 }
01268 }
01269
01270
01271
01272
01273
01274 std::vector<std::pair<std::string,ConfigurationTree> > ConfigurationTree::getChildren(
01275 std::map<std::string /*relative-path*/, std::string /*value*/> filterMap) const
01276 {
01277 std::vector<std::pair<std::string,ConfigurationTree> > retMap;
01278
01279
01280
01281 bool filtering = filterMap.size();
01282 bool skip;
01283 std::string fieldValue;
01284
01285 std::vector<std::string> childrenNames = getChildrenNames();
01286 for(auto &childName : childrenNames)
01287 {
01288
01289
01290 if(filtering)
01291 {
01292
01293 skip = false;
01294
01295
01296 for(const auto &filterPair:filterMap)
01297 {
01298 std::string filterPath = childName + "/" + filterPair.first;
01299 try
01300 {
01301
01302
01303
01304 std::istringstream f(filterPair.second);
01305
01306 skip = true;
01307
01308 while (getline(f, fieldValue, ','))
01309 {
01310
01311
01312
01313
01314
01315
01316 __MOUT__ << "\t\tCheck: " << filterPair.first <<
01317 " == " << fieldValue << " ??? " <<
01318 this->getNode(filterPath).getValueAsString(true) <<
01319 std::endl;
01320 if(this->getNode(filterPath).getValueAsString(true) ==
01321 ConfigurationView::decodeURIComponent(fieldValue))
01322 {
01323
01324 skip = false;
01325 break;
01326 }
01327 }
01328 }
01329 catch(...)
01330 {
01331 __SS__ << "Failed to access filter path '" <<
01332 filterPath << "' - aborting." << std::endl;
01333 __MOUT_ERR__ << "\n" << ss.str();
01334 throw std::runtime_error(ss.str());
01335 }
01336
01337 if(skip) break;
01338 }
01339
01340 if(skip) continue;
01341
01342 __MOUT__ << "\tChild accepted: " << childName << std::endl;
01343 }
01344
01345 retMap.push_back(std::pair<std::string,ConfigurationTree>(childName,
01346 this->getNode(childName, true)));
01347 }
01348
01349
01350 return retMap;
01351 }
01352
01353
01354
01355
01356 std::map<std::string,ConfigurationTree> ConfigurationTree::getChildrenMap(void) const
01357 {
01358 std::map<std::string,ConfigurationTree> retMap;
01359
01360
01361
01362 std::vector<std::string> childrenNames = getChildrenNames();
01363 for(auto& childName : childrenNames)
01364 {
01365
01366 retMap.insert(std::pair<std::string,ConfigurationTree>(childName, this->getNode(childName)));
01367 }
01368
01369
01370 return retMap;
01371 }
01372
01373
01374 bool ConfigurationTree::isConfigurationNode(void) const
01375 {
01376 return (row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID);
01377 }
01378
01379
01380
01381
01382 std::vector<std::string> ConfigurationTree::getChildrenNames(void) const
01383 {
01384 std::vector<std::string> retSet;
01385
01386 if(!configView_)
01387 {
01388 __SS__ << "Can not get children names of '" <<
01389 getValueAsString() <<
01390 "' with null configuration view pointer!" << std::endl;
01391 if(isLinkNode() && isDisconnected())
01392 ss << " This node is a disconnected link to " <<
01393 getDisconnectedTableName() << std::endl;
01394 __MOUT_ERR__ << "\n" << ss.str();
01395 throw std::runtime_error(ss.str());
01396 }
01397
01398 if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID)
01399 {
01400
01401
01402
01403 for(unsigned int r = 0; r<configView_->getNumberOfRows(); ++r)
01404 if(groupId_ == "" ||
01405 configView_->isEntryInGroup(r,childLinkIndex_,groupId_))
01406
01407
01408 retSet.push_back(configView_->getDataView()[r][configView_->getColUID()]);
01409 }
01410 else if(row_ == ConfigurationView::INVALID)
01411 throw std::runtime_error("Malformed ConfigurationTree");
01412 else if(col_ == ConfigurationView::INVALID)
01413 {
01414
01415
01416
01417 for(unsigned int c = 0; c<configView_->getNumberOfColumns(); ++c)
01418 if(c == configView_->getColUID() ||
01419 configView_->getColumnInfo(c).isChildLinkGroupID() ||
01420 configView_->getColumnInfo(c).isChildLinkUID())
01421 continue;
01422 else
01423 retSet.push_back(configView_->getColumnInfo(c).getName());
01424 }
01425 else
01426 {
01427 __MOUT__ << "\n\nError occurred looking for children of nodeName=" << getValueName() << "\n\n" << std::endl;
01428 throw std::runtime_error("Invalid depth! getChildrenValues() called from a value point in the Configuration Tree.");
01429 }
01430
01431 return retSet;
01432 }
01433
01434
01435
01436
01437
01438