00001 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationView.h"
00002
00003 #include <iostream>
00004 #include <sstream>
00005 #include <cstdlib>
00006 #include <regex>
00007
00008 using namespace ots;
00009
00010 #undef __MF_SUBJECT__
00011 #define __MF_SUBJECT__ "ConfigurationView"
00012 #undef __MF_HDR__
00013 #define __MF_HDR__ tableName_ << ":v" << version_ << ":" << __COUT_HDR_FL__
00014
00015 const unsigned int ConfigurationView::INVALID = -1;
00016
00017
00018 ConfigurationView::ConfigurationView(const std::string &name)
00019 : uniqueStorageIdentifier_ (""),
00020 tableName_ (name),
00021 version_ (ConfigurationVersion::INVALID),
00022 comment_ (""),
00023 author_ (""),
00024 creationTime_ (time(0)),
00025 lastAccessTime_ (0),
00026 colUID_ (INVALID),
00027 fillWithLooseColumnMatching_(false),
00028 sourceColumnMismatchCount_ (0),
00029 sourceColumnMissingCount_ (0)
00030 {}
00031
00032
00033 ConfigurationView::~ConfigurationView(void)
00034 {}
00035
00036
00037
00038
00039
00040 ConfigurationView& ConfigurationView::operator=(const ConfigurationView src)
00041 {
00042 __SS__ << "Invalid use of operator=... Should not directly copy a ConfigurationView. Please use ConfigurationView::copy(sourceView,author,comment)";
00043 throw std::runtime_error(ss.str());
00044 }
00045
00046
00047 ConfigurationView& ConfigurationView::copy(const ConfigurationView &src,
00048 ConfigurationVersion destinationVersion,
00049 const std::string &author)
00050 {
00051 tableName_ = src.tableName_;
00052 version_ = destinationVersion;
00053 comment_ = src.comment_;
00054 author_ = author;
00055
00056 lastAccessTime_ = time(0);
00057 columnsInfo_ = src.columnsInfo_;
00058 theDataView_ = src.theDataView_;
00059 sourceColumnNames_ = src.sourceColumnNames_;
00060 init();
00061 return *this;
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071 void ConfigurationView::init(void)
00072 {
00073 try
00074 {
00075
00076
00077 std::set<std::string> colNameSet;
00078 std::string capsColName, colName;
00079 for(auto &colInfo: columnsInfo_)
00080 {
00081 colName = colInfo.getStorageName();
00082 if(colName == "COMMENT_DESCRIPTION")
00083 colName = "COMMENT";
00084 capsColName = "";
00085 for(unsigned int i=0;i<colName.size(); ++i)
00086 {
00087 if(colName[i] == '_') continue;
00088 capsColName += colName[i];
00089 }
00090
00091 colNameSet.emplace(capsColName);
00092 }
00093
00094 if(colNameSet.size() != columnsInfo_.size())
00095 {
00096 __SS__ << "Configuration Error:\t" <<
00097 " Columns names must be unique! There are " << columnsInfo_.size() <<
00098 " columns and the unique name count is " << colNameSet.size() << std::endl;
00099 __MOUT_ERR__ << "\n" << ss.str();
00100
00101 throw std::runtime_error(ss.str());
00102 }
00103
00104 getOrInitColUID();
00105
00106
00107 unsigned int colPos;
00108 if((colPos = findColByType(ViewColumnInfo::TYPE_COMMENT)) != INVALID)
00109 {
00110 if(columnsInfo_[colPos].getName() != "CommentDescription")
00111 {
00112 __SS__ << "Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
00113 " data type column must have name=" <<
00114 "CommentDescription" << std::endl;
00115 __MOUT_ERR__ << "\n" << ss.str();
00116 throw std::runtime_error(ss.str());
00117 }
00118
00119 if(findColByType(ViewColumnInfo::TYPE_COMMENT,colPos+1) != INVALID)
00120 {
00121 __SS__ << "Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
00122 " data type in column " <<
00123 columnsInfo_[colPos].getName() <<
00124 " is repeated. This is not allowed." << std::endl;
00125 __MOUT_ERR__ << "\n" << ss.str();
00126 throw std::runtime_error(ss.str());
00127 }
00128
00129 if(colPos != getNumberOfColumns()-3)
00130 {
00131 __SS__ << "Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
00132 " data type column must be 3rd to last (in column " <<
00133 getNumberOfColumns()-3 << ")." << std::endl;
00134 __MOUT_ERR__ << "\n" << ss.str();
00135 throw std::runtime_error(ss.str());
00136 }
00137 }
00138 else
00139 {
00140 __SS__ << "Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
00141 " data type column " <<" is missing. This is not allowed." << std::endl;
00142 __MOUT_ERR__ << "\n" << ss.str();
00143 throw std::runtime_error(ss.str());
00144 }
00145
00146
00147 if((colPos = findColByType(ViewColumnInfo::TYPE_AUTHOR)) != INVALID)
00148 {
00149 if(findColByType(ViewColumnInfo::TYPE_AUTHOR,colPos+1) != INVALID)
00150 {
00151 __SS__ << "Configuration Error:\t" << ViewColumnInfo::TYPE_AUTHOR <<
00152 " data type in column " <<
00153 columnsInfo_[colPos].getName() <<
00154 " is repeated. This is not allowed." << std::endl;
00155 __MOUT_ERR__ << "\n" << ss.str();
00156 throw std::runtime_error(ss.str());
00157 }
00158
00159 if(colPos != getNumberOfColumns()-2)
00160 {
00161 __SS__ << "Configuration Error:\t" << ViewColumnInfo::TYPE_AUTHOR <<
00162 " data type column must be 2nd to last (in column " <<
00163 getNumberOfColumns()-2 << ")." << std::endl;
00164 __MOUT_ERR__ << "\n" << ss.str();
00165 throw std::runtime_error(ss.str());
00166 }
00167 }
00168 else
00169 {
00170 __SS__ << "Configuration Error:\t" << ViewColumnInfo::TYPE_AUTHOR <<
00171 " data type column " <<" is missing. This is not allowed." << std::endl;
00172 __MOUT_ERR__ << "\n" << ss.str();
00173 throw std::runtime_error(ss.str());
00174 }
00175
00176
00177 if((colPos = findColByType(ViewColumnInfo::TYPE_TIMESTAMP)) != INVALID)
00178 {
00179 if(findColByType(ViewColumnInfo::TYPE_TIMESTAMP,colPos+1) != INVALID)
00180 {
00181 __SS__ << "Configuration Error:\t" << ViewColumnInfo::TYPE_TIMESTAMP <<
00182 " data type in column " <<
00183 columnsInfo_[colPos].getName() << " is repeated. This is not allowed." <<
00184 std::endl;
00185 __MOUT_ERR__ << "\n" << ss.str();
00186 throw std::runtime_error(ss.str());
00187 }
00188
00189 if(colPos != getNumberOfColumns()-1)
00190 {
00191 __SS__ << "Configuration Error:\t" << ViewColumnInfo::TYPE_TIMESTAMP <<
00192 " data type column must be last (in column " <<
00193 getNumberOfColumns()-1 << ")." << std::endl;
00194 __MOUT_ERR__ << "\n" << ss.str();
00195 throw std::runtime_error(ss.str());
00196 }
00197 }
00198 else
00199 {
00200 __SS__ << "Configuration Error:\t" << ViewColumnInfo::TYPE_TIMESTAMP <<
00201 " data type column " <<" is missing. This is not allowed." << std::endl;
00202 __MOUT_ERR__ << "\n" << ss.str();
00203 throw std::runtime_error(ss.str());
00204 }
00205
00206
00207
00208
00209 std::set<std::string > uidSet;
00210 for(unsigned int row = 0; row < getNumberOfRows(); ++row)
00211 {
00212 if(uidSet.find(theDataView_[row][colUID_]) != uidSet.end())
00213 {
00214 __SS__ << ("Entries in UID are not unique. Specifically at row=" +
00215 std::to_string(row) + " value=" + theDataView_[row][colUID_])<< std::endl;
00216 __MOUT_ERR__ << "\n" << ss.str();
00217 throw std::runtime_error(ss.str());
00218 }
00219
00220 if(theDataView_[row][colUID_].size() == 0)
00221 {
00222 __SS__ << "An invalid UID '" << theDataView_[row][colUID_] << "' " <<
00223 " was identified. UIDs must contain at least 1 character." <<
00224 std::endl;
00225 throw std::runtime_error(ss.str());
00226 }
00227
00228 for(unsigned int i=0;i<theDataView_[row][colUID_].size();++i)
00229 if(!(
00230 (theDataView_[row][colUID_][i] >= 'A' && theDataView_[row][colUID_][i] <= 'Z') ||
00231 (theDataView_[row][colUID_][i] >= 'a' && theDataView_[row][colUID_][i] <= 'z') ||
00232 (theDataView_[row][colUID_][i] >= '0' && theDataView_[row][colUID_][i] <= '9') ||
00233 (theDataView_[row][colUID_][i] == '-' || theDataView_[row][colUID_][i] <= '_')
00234 ))
00235 {
00236 __SS__ << "An invalid UID '" << theDataView_[row][colUID_] << "' " <<
00237 " was identified. UIDs must contain only letters, numbers," <<
00238 "dashes, and underscores." << std::endl;
00239 throw std::runtime_error(ss.str());
00240 }
00241
00242 uidSet.insert(theDataView_[row][colUID_]);
00243 }
00244 if(uidSet.size() != getNumberOfRows())
00245 {
00246 __SS__ << "Entries in UID are not unique!" <<
00247 "There are " << getNumberOfRows() <<
00248 " rows and the unique UID count is " << uidSet.size() << std::endl;
00249 __MOUT_ERR__ << "\n" << ss.str();
00250 throw std::runtime_error(ss.str());
00251 }
00252
00253
00254 colPos = (unsigned int)-1;
00255 while((colPos = findColByType(ViewColumnInfo::TYPE_UNIQUE_DATA,colPos+1)) != INVALID)
00256 {
00257 std::set<std::string > uDataSet;
00258 for(unsigned int row = 0; row < getNumberOfRows(); ++row)
00259 {
00260 if(uDataSet.find(theDataView_[row][colPos]) != uDataSet.end())
00261 {
00262 __SS__ << "Entries in Unique Data column " <<
00263 columnsInfo_[colPos].getName() <<
00264 (" are not unique. Specifically at row=" +
00265 std::to_string(row) + " value=" + theDataView_[row][colPos]) <<
00266 std::endl;
00267 __MOUT_ERR__ << "\n" << ss.str();
00268 throw std::runtime_error(ss.str());
00269 }
00270 uDataSet.insert(theDataView_[row][colPos]);
00271 }
00272 if(uDataSet.size() != getNumberOfRows())
00273 {
00274 __SS__ << "Entries in Unique Data column " <<
00275 columnsInfo_[colPos].getName() << " are not unique!" <<
00276 "There are " << getNumberOfRows() <<
00277 " rows and the unique data count is " << uDataSet.size() << std::endl;
00278 __MOUT_ERR__ << "\n" << ss.str();
00279 throw std::runtime_error(ss.str());
00280 }
00281 }
00282
00283 auto rowDefaults = getDefaultRowValues();
00284
00285
00286
00287
00288
00289
00290 std::set<std::string> groupIdIndexes, childLinkIndexes, childLinkIdLabels;
00291 unsigned int groupIdIndexesCount = 0, childLinkIndexesCount = 0, childLinkIdLabelsCount = 0;
00292 for(unsigned int col = 0; col < getNumberOfColumns(); ++col)
00293 {
00294 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
00295 {
00296 const std::vector<std::string>& theDataChoices =
00297 columnsInfo_[col].getDataChoices();
00298
00299
00300 if(theDataChoices.size() && theDataChoices[0] ==
00301 "arbitraryBool=1")
00302 continue;
00303
00304 bool found;
00305 for(unsigned int row = 0; row < getNumberOfRows(); ++row)
00306 {
00307 found = false;
00308
00309 if(theDataView_[row][col] == rowDefaults[col])
00310 continue;
00311
00312 for(const auto &choice:theDataChoices)
00313 {
00314 if(theDataView_[row][col] == choice)
00315 {
00316 found = true;
00317 break;
00318 }
00319 }
00320 if(!found)
00321 {
00322 __SS__ << "Configuration Error:\t'" << theDataView_[row][col] << "' in column " <<
00323 columnsInfo_[col].getName() << " is not a valid Fixed Choice option. " <<
00324 "Possible values are as follows: ";
00325
00326 for(unsigned int i = 0; i < columnsInfo_[col].getDataChoices().size(); ++i)
00327 {
00328 if(i) ss << ", ";
00329 ss << columnsInfo_[col].getDataChoices()[i];
00330 }
00331 ss << "." << std::endl;
00332 __MOUT_ERR__ << "\n" << ss.str();
00333 throw std::runtime_error(ss.str());
00334 }
00335 }
00336 }
00337 if(columnsInfo_[col].isChildLink())
00338 {
00339
00340
00341 const std::vector<std::string>& theDataChoices =
00342 columnsInfo_[col].getDataChoices();
00343
00344
00345 if(!theDataChoices.size() ||
00346 theDataChoices[0] == "arbitraryBool=1")
00347 continue;
00348
00349 bool found;
00350 for(unsigned int row = 0; row < getNumberOfRows(); ++row)
00351 {
00352 found = false;
00353
00354 for(const auto &choice:theDataChoices)
00355 {
00356 if(theDataView_[row][col] == choice)
00357 {
00358 found = true;
00359 break;
00360 }
00361 }
00362 if(!found)
00363 {
00364 __SS__ << "Configuration Error:\t'" << theDataView_[row][col] << "' in column " <<
00365 columnsInfo_[col].getName() << " is not a valid Fixed Choice option. " <<
00366 "Possible values are as follows: ";
00367
00368 for(unsigned int i = 0; i < columnsInfo_[col].getDataChoices().size(); ++i)
00369 {
00370 if(i) ss << ", ";
00371 ss << columnsInfo_[col].getDataChoices()[i];
00372 }
00373 ss << "." << std::endl;
00374 __MOUT_ERR__ << "\n" << ss.str();
00375 throw std::runtime_error(ss.str());
00376 }
00377 }
00378 }
00379 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_ON_OFF)
00380 for(unsigned int row = 0; row < getNumberOfRows(); ++row)
00381 {
00382 if (theDataView_[row][col] == "1" || theDataView_[row][col] == "on" || theDataView_[row][col] == "On" || theDataView_[row][col] == "ON")
00383 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_ON;
00384 else if (theDataView_[row][col] == "0" || theDataView_[row][col] == "off" || theDataView_[row][col] == "Off" || theDataView_[row][col] == "OFF")
00385 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_OFF;
00386 else
00387 {
00388 __SS__ << "Configuration Error:\t" << theDataView_[row][col] << " in column " <<
00389 columnsInfo_[col].getName() << " is not a valid Type (On/Off) std::string. Possible values are 1, on, On, ON, 0, off, Off, OFF." << std::endl;
00390 __MOUT_ERR__ << "\n" << ss.str();
00391 throw std::runtime_error(ss.str());
00392 }
00393 }
00394 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_TRUE_FALSE)
00395 for(unsigned int row = 0; row < getNumberOfRows(); ++row)
00396 {
00397 if (theDataView_[row][col] == "1" || theDataView_[row][col] == "true" || theDataView_[row][col] == "True" || theDataView_[row][col] == "TRUE")
00398 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_TRUE;
00399 else if (theDataView_[row][col] == "0" || theDataView_[row][col] == "false" || theDataView_[row][col] == "False" || theDataView_[row][col] == "FALSE")
00400 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_FALSE;
00401 else
00402 {
00403 __SS__ << "Configuration Error:\t" << theDataView_[row][col] << " in column " <<
00404 columnsInfo_[col].getName() << " is not a valid Type (True/False) std::string. Possible values are 1, true, True, TRUE, 0, false, False, FALSE." << std::endl;
00405 __MOUT_ERR__ << "\n" << ss.str();
00406 throw std::runtime_error("Invalid true/false usage");
00407 }
00408 }
00409 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_YES_NO)
00410 for(unsigned int row = 0; row < getNumberOfRows(); ++row)
00411 {
00412 if (theDataView_[row][col] == "1" || theDataView_[row][col] == "yes" || theDataView_[row][col] == "Yes" || theDataView_[row][col] == "YES")
00413 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_YES;
00414 else if (theDataView_[row][col] == "0" || theDataView_[row][col] == "no" || theDataView_[row][col] == "No" || theDataView_[row][col] == "NO")
00415 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_NO;
00416 else
00417 {
00418 __SS__ << "Configuration Error:\t" << theDataView_[row][col] << " in column " <<
00419 columnsInfo_[col].getName() << " is not a valid Type (Yes/No) std::string. Possible values are 1, yes, Yes, YES, 0, no, No, NO." << std::endl;
00420 __MOUT_ERR__ << "\n" << ss.str();
00421 throw std::runtime_error(ss.str());
00422 }
00423 }
00424 else if(columnsInfo_[col].isGroupID())
00425 {
00426 colLinkGroupIDs_[columnsInfo_[col].getChildLinkIndex()] = col;
00427
00428 groupIdIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
00429 ++groupIdIndexesCount;
00430 }
00431 else if(columnsInfo_[col].isChildLink())
00432 {
00433
00434 for(unsigned int row = 0; row < getNumberOfRows(); ++row)
00435 if(theDataView_[row][col] == "NoLink" ||
00436 theDataView_[row][col] == "No_Link" ||
00437 theDataView_[row][col] == "NOLINK" ||
00438 theDataView_[row][col] == "NO_LINK" ||
00439 theDataView_[row][col] == "Nolink" ||
00440 theDataView_[row][col] == "nolink" ||
00441 theDataView_[row][col] == "noLink")
00442 theDataView_[row][col] = ViewColumnInfo::DATATYPE_LINK_DEFAULT;
00443
00444
00445 childLinkIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
00446 ++childLinkIndexesCount;
00447
00448
00449 if(columnsInfo_[col].getDataType() != ViewColumnInfo::DATATYPE_STRING)
00450 {
00451 __SS__ << "Configuration Error:\t" << "Column " << col <<
00452 " with name " << columnsInfo_[col].getName() <<
00453 " is a Child Link column and has an illegal data type of '" <<
00454 columnsInfo_[col].getDataType() <<
00455 "'. The data type for Child Link columns must be " <<
00456 ViewColumnInfo::DATATYPE_STRING << std::endl;
00457 __MOUT_ERR__ << "\n" << ss.str();
00458 throw std::runtime_error(ss.str());
00459 }
00460
00461 }
00462 else if(columnsInfo_[col].isChildLinkUID() ||
00463 columnsInfo_[col].isChildLinkGroupID())
00464 {
00465
00466 childLinkIdLabels.emplace(columnsInfo_[col].getChildLinkIndex());
00467 ++childLinkIdLabelsCount;
00468
00469
00470 for(unsigned int row = 0; row < getNumberOfRows(); ++row)
00471 if(theDataView_[row][col] == "")
00472 theDataView_[row][col] = rowDefaults[col];
00473
00474 }
00475 }
00476
00477
00478 if(groupIdIndexes.size() != groupIdIndexesCount)
00479 {
00480 __SS__ << ("GroupId Labels are not unique!") <<
00481 "There are " << groupIdIndexesCount <<
00482 " GroupId Labels and the unique count is " << groupIdIndexes.size() << std::endl;
00483 __MOUT_ERR__ << "\n" << ss.str();
00484 throw std::runtime_error(ss.str());
00485 }
00486 if(childLinkIndexes.size() != childLinkIndexesCount)
00487 {
00488 __SS__ << ("Child Link Labels are not unique!") <<
00489 "There are " << childLinkIndexesCount <<
00490 " Child Link Labels and the unique count is " << childLinkIndexes.size() << std::endl;
00491 __MOUT_ERR__ << "\n" << ss.str();
00492 throw std::runtime_error(ss.str());
00493 }
00494 if(childLinkIdLabels.size() != childLinkIdLabelsCount)
00495 {
00496 __SS__ << ("Child Link ID Labels are not unique!") <<
00497 "There are " << childLinkIdLabelsCount <<
00498 " Child Link ID Labels and the unique count is " << childLinkIdLabels.size() << std::endl;
00499 __MOUT_ERR__ << "\n" << ss.str();
00500 throw std::runtime_error(ss.str());
00501 }
00502
00503 }
00504 catch(...)
00505 {
00506 __MOUT__ << "Error occured in ConfigurationView::init() for version=" << version_ << std::endl;
00507 throw;
00508 }
00509 }
00510
00511
00512
00513
00514
00515 void ConfigurationView::getValue(std::string& value, unsigned int row, unsigned int col, bool convertEnvironmentVariables) const
00516 {
00517
00518
00519 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
00520 {
00521 __SS__ << "Invalid row col requested" << std::endl;
00522 __MOUT_ERR__ << "\n" << ss.str();
00523 throw std::runtime_error(ss.str());
00524 }
00525
00526 value = validateValueForColumn(theDataView_[row][col],col,convertEnvironmentVariables);
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 }
00563
00564
00565
00566
00567
00568
00569 std::string ConfigurationView::validateValueForColumn(const std::string& value, unsigned int col, bool convertEnvironmentVariables) const
00570 {
00571
00572 if(col >= columnsInfo_.size())
00573 {
00574 __SS__ << "Invalid col requested" << std::endl;
00575 __MOUT_ERR__ << "\n" << ss.str();
00576 throw std::runtime_error(ss.str());
00577 }
00578
00579 std::string retValue;
00580
00581 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING)
00582 retValue = convertEnvironmentVariables?convertEnvVariables(value):value;
00583 else if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_TIME)
00584 {
00585 retValue.resize(30);
00586 time_t timestamp(
00587 strtol((convertEnvironmentVariables?convertEnvVariables(value):value).c_str(),
00588 0,10));
00589 struct tm tmstruct;
00590 ::localtime_r(×tamp, &tmstruct);
00591 ::strftime(&retValue[0], 30, "%c %Z", &tmstruct);
00592 retValue.resize(strlen(retValue.c_str()));
00593 }
00594 else
00595 {
00596 __SS__ << "\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
00597 << " in configuration " << tableName_
00598 << " at column=" << columnsInfo_[col].getName()
00599 << " for getValue with type '" << ots_demangle(typeid(retValue).name())
00600 << "'" << std::endl;
00601 __MOUT_ERR__ << "\n" << ss.str();
00602 throw std::runtime_error(ss.str());
00603 }
00604
00605 return retValue;
00606 }
00607
00608
00609
00610
00611
00612
00613 std::string ConfigurationView::getValueAsString(unsigned int row, unsigned int col,
00614 bool convertEnvironmentVariables) const
00615 {
00616 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
00617 throw std::runtime_error("Invalid row col requested");
00618
00619
00620
00621 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_ON_OFF)
00622 {
00623 if (theDataView_[row][col] == "1" || theDataView_[row][col] == "on" || theDataView_[row][col] == "On" || theDataView_[row][col] == "ON")
00624 return ViewColumnInfo::TYPE_VALUE_ON;
00625 else
00626 return ViewColumnInfo::TYPE_VALUE_OFF;
00627 }
00628 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_TRUE_FALSE)
00629 {
00630 if (theDataView_[row][col] == "1" || theDataView_[row][col] == "true" || theDataView_[row][col] == "True" || theDataView_[row][col] == "TRUE")
00631 return ViewColumnInfo::TYPE_VALUE_TRUE;
00632 else
00633 return ViewColumnInfo::TYPE_VALUE_FALSE;
00634 }
00635 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_YES_NO)
00636 {
00637 if (theDataView_[row][col] == "1" || theDataView_[row][col] == "yes" || theDataView_[row][col] == "Yes" || theDataView_[row][col] == "YES")
00638 return ViewColumnInfo::TYPE_VALUE_YES;
00639 else
00640 return ViewColumnInfo::TYPE_VALUE_NO;
00641 }
00642
00643
00644 return convertEnvironmentVariables?convertEnvVariables(theDataView_[row][col]):
00645 theDataView_[row][col];
00646 }
00647
00648
00649
00650
00651
00652
00653
00654
00655 std::string ConfigurationView::getEscapedValueAsString(unsigned int row, unsigned int col,
00656 bool convertEnvironmentVariables) const
00657 {
00658 std::string val = getValueAsString(row,col,convertEnvironmentVariables);
00659 std::string retVal = "";
00660 retVal.reserve(val.size());
00661 for(unsigned int i=0;i<val.size();++i)
00662 {
00663 if(val[i] == '\n')
00664 retVal += "\\n";
00665 else if(val[i] == '\t')
00666 retVal += "\\t";
00667 else if(val[i] == '\r')
00668 retVal += "\\r";
00669 else
00670 {
00671
00672 if(val[i] == '"' ||
00673 val[i] == '\\')
00674 retVal += '\\';
00675 retVal += val[i];
00676 }
00677 }
00678 return retVal;
00679 }
00680
00681
00682 std::string ConfigurationView::convertEnvVariables(const std::string& data) const
00683 {
00684 std::string converted = data;
00685 if(data.find("${") != std::string::npos)
00686 {
00687 unsigned int begin = data.find("${");
00688 unsigned int end = data.find("}");
00689 std::string envVariable = data.substr(begin+2, end-begin-2);
00690
00691 if(getenv(envVariable.c_str()) != nullptr)
00692 {
00693 return convertEnvVariables(converted.replace(begin,end-begin+1,getenv(envVariable.c_str())));
00694 }
00695 else
00696 throw std::runtime_error("In configuration " + tableName_ + " the environmental variable: " + envVariable + " is not set! Please make sure you set it before continuing!");
00697 }
00698 return converted;
00699 }
00700
00701
00702
00703
00704 void ConfigurationView::setValue(const std::string &value, unsigned int row, unsigned int col)
00705 {
00706 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
00707 {
00708 __SS__ << "Invalid row (" << row << ") col (" << col << ") requested!" << std::endl;
00709 throw std::runtime_error(ss.str());
00710 }
00711
00712 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING)
00713 theDataView_[row][col] = value;
00714 else
00715 {
00716
00717 __SS__ << "\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
00718 << " in configuration " << tableName_
00719 << " at column=" << columnsInfo_[col].getName()
00720 << " for setValue with type '" << ots_demangle(typeid(value).name())
00721 << "'" << std::endl;
00722 throw std::runtime_error(ss.str());
00723 }
00724 }
00725 void ConfigurationView::setValue(const char *value, unsigned int row, unsigned int col)
00726 { setValue(std::string(value),row,col); }
00727
00728
00729
00730
00731 void ConfigurationView::setValueAsString(const std::string &value, unsigned int row, unsigned int col)
00732 {
00733 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
00734 {
00735 __SS__ << "Invalid row (" << row << ") col (" << col << ") requested!" << std::endl;
00736 throw std::runtime_error(ss.str());
00737 }
00738
00739 theDataView_[row][col] = value;
00740 }
00741
00742
00743
00744
00745 const unsigned int ConfigurationView::getOrInitColUID (void)
00746 {
00747 if(colUID_ != INVALID) return colUID_;
00748
00749
00750 colUID_ = findColByType(ViewColumnInfo::TYPE_UID);
00751 if(colUID_ == INVALID)
00752 {
00753 __MOUT__ << "Column Types: " << std::endl;
00754 for(unsigned int col=0; col<columnsInfo_.size(); ++col)
00755 std::cout << columnsInfo_[col].getType() << "() " << columnsInfo_[col].getName() << std::endl;
00756 __SS__ << "\tMissing UID Column in table named '" << tableName_ << "'" << std::endl;
00757 __MOUT_ERR__ << "\n" << ss.str() << std::endl;
00758 throw std::runtime_error(ss.str());
00759 }
00760 return colUID_;
00761 }
00762
00763
00764
00765
00766 const unsigned int ConfigurationView::getColUID (void) const
00767 {
00768 if(colUID_ != INVALID) return colUID_;
00769
00770 __MOUT__ << "Column Types: " << std::endl;
00771 for(unsigned int col=0; col<columnsInfo_.size(); ++col)
00772 std::cout << columnsInfo_[col].getType() << "() " << columnsInfo_[col].getName() << std::endl;
00773
00774 __SS__ << ("Missing UID Column in config named " + tableName_ +
00775 ". (Possibly ConfigurationView was just not initialized?" +
00776 "This is the const call so can not alter class members)") << std::endl;
00777 __MOUT_ERR__ << "\n" << ss.str() << std::endl;
00778 throw std::runtime_error(ss.str());
00779 }
00780
00781
00782
00783
00784 void ConfigurationView::addRowToGroup(const unsigned int &row,
00785 const unsigned int &col,
00786 const std::string &groupID,
00787 const std::string &colDefault)
00788 {
00789 if(isEntryInGroupCol(row,col,groupID))
00790 {
00791 __SS__ << "GroupID (" << groupID <<
00792 ") added to row (" << row
00793 << " is already present!" << std::endl;
00794 throw std::runtime_error(ss.str());
00795 }
00796
00797
00798
00799
00800
00801
00802 if(getDataView()[row][col] == "" ||
00803 getDataView()[row][col] == colDefault)
00804 setValue(
00805 groupID,
00806 row,col);
00807 else
00808 setValue(
00809 groupID + " | " + getDataView()[row][col],
00810 row,col);
00811
00812
00813 }
00814
00815
00816
00817
00818 void ConfigurationView::removeRowFromGroup(const unsigned int &row,
00819 const unsigned int &col,
00820 const std::string &groupNeedle)
00821 {
00822 __MOUT__ << "groupNeedle " << groupNeedle << std::endl;
00823 std::set<std::string> groupIDList;
00824 if(!isEntryInGroupCol(row,col,groupNeedle,&groupIDList))
00825 {
00826 __SS__ << "GroupID (" << groupNeedle <<
00827 ") removed from row (" << row
00828 << ") was already removed!" << std::endl;
00829 throw std::runtime_error(ss.str());
00830 }
00831
00832
00833
00834
00835
00836 std::string newValue = "";
00837 unsigned int cnt = 0;
00838 for(const auto & groupID : groupIDList)
00839 {
00840
00841 if(groupID == groupNeedle) continue;
00842
00843 if(cnt) newValue += " | ";
00844 newValue += groupID;
00845 }
00846 setValue(newValue,row,col);
00847
00848
00849 }
00850
00851
00852
00853
00854
00855
00856
00857 bool ConfigurationView::isEntryInGroup(const unsigned int &r,
00858 const std::string &childLinkIndex,
00859 const std::string &groupNeedle) const
00860 {
00861 unsigned int c = getColLinkGroupID(childLinkIndex);
00862
00863 return isEntryInGroupCol(r,c,groupNeedle);
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876 bool ConfigurationView::isEntryInGroupCol(const unsigned int &r,
00877 const unsigned int &c, const std::string &groupNeedle,
00878 std::set<std::string> *groupIDList) const
00879 {
00880 unsigned int i=0;
00881 unsigned int j=0;
00882 bool found = false;
00883
00884
00885
00886
00887 for(;j<theDataView_[r][c].size();++j)
00888 if((theDataView_[r][c][j] == ' ' ||
00889 theDataView_[r][c][j] == '|')
00890 && i == j)
00891 ++i;
00892 else if((theDataView_[r][c][j] == ' ' ||
00893 theDataView_[r][c][j] == '|')
00894 && i != j)
00895 {
00896 if(groupIDList) groupIDList->emplace(theDataView_[r][c].substr(i,j-i));
00897
00898
00899
00900 if(groupNeedle == theDataView_[r][c].substr(i,j-i))
00901 {
00902 if(!groupIDList)
00903 return true;
00904 found = true;
00905 }
00906
00907 i = j+1;
00908 }
00909
00910 if(i != j)
00911 {
00912 if(groupIDList) groupIDList->emplace(theDataView_[r][c].substr(i,j-i));
00913
00914
00915
00916 if(groupNeedle == theDataView_[r][c].substr(i,j-i))
00917 return true;
00918 }
00919
00920 return found;
00921 }
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931 std::set<std::string> ConfigurationView::getSetOfGroupIDs(const std::string &childLinkIndex,
00932 unsigned int r) const
00933 {
00934 unsigned int c = getColLinkGroupID(childLinkIndex);
00935
00936
00937
00938 std::set<std::string> retSet;
00939
00940 unsigned int i=0;
00941 unsigned int j=0;
00942
00943 if(r != (unsigned int)-1)
00944 {
00945 if(r >= getNumberOfRows())
00946 {
00947 __SS__ << "Invalid row requested!" << std::endl;
00948 throw std::runtime_error(ss.str());
00949 }
00950
00951
00952
00953 for(;j<theDataView_[r][c].size();++j)
00954 if((theDataView_[r][c][j] == ' ' ||
00955 theDataView_[r][c][j] == '|')
00956 && i == j)
00957 ++i;
00958 else if((theDataView_[r][c][j] == ' ' ||
00959 theDataView_[r][c][j] == '|')
00960 && i != j)
00961 {
00962
00963
00964
00965
00966 retSet.emplace(theDataView_[r][c].substr(i,j-i));
00967
00968
00969 i = j+1;
00970 }
00971
00972 if(i != j)
00973 retSet.emplace(theDataView_[r][c].substr(i,j-i));
00974 }
00975 else
00976 {
00977
00978 for(r=0;r<getNumberOfRows();++r)
00979 {
00980 i=0;
00981 j=0;
00982
00983
00984
00985
00986
00987 for(;j<theDataView_[r][c].size();++j)
00988 {
00989
00990
00991 if((theDataView_[r][c][j] == ' ' ||
00992 theDataView_[r][c][j] == '|')
00993 && i == j)
00994 ++i;
00995 else if((theDataView_[r][c][j] == ' ' ||
00996 theDataView_[r][c][j] == '|')
00997 && i != j)
00998 {
00999
01000
01001
01002 retSet.emplace(theDataView_[r][c].substr(i,j-i));
01003
01004
01005 i = j+1;
01006 }
01007 }
01008
01009 if(i != j)
01010 {
01011
01012
01013 retSet.emplace(theDataView_[r][c].substr(i,j-i));
01014 }
01015 }
01016 }
01017
01018 return retSet;
01019 }
01020
01021
01022
01023
01024 const unsigned int ConfigurationView::getColLinkGroupID(const std::string &childLinkIndex) const
01025 {
01026 std::map<std::string, unsigned int>::const_iterator it = colLinkGroupIDs_.find(childLinkIndex);
01027 if(it !=
01028 colLinkGroupIDs_.end())
01029 return it->second;
01030
01031 __MOUT__ << "Existing Column Types: " << std::endl;
01032 for(unsigned int col=0; col<columnsInfo_.size(); ++col)
01033 std::cout << columnsInfo_[col].getType() << "() " << columnsInfo_[col].getName() << std::endl;
01034
01035 __SS__ << ("Incompatible table for this group link. Table '" +
01036 tableName_ + "' is missing a GroupID column with data type '" +
01037 (ViewColumnInfo::TYPE_START_GROUP_ID + "-" + childLinkIndex) +
01038 "'." ) << std::endl;
01039 __MOUT_ERR__ << "\n" << ss.str();
01040 throw std::runtime_error(ss.str());
01041 }
01042
01043
01044 unsigned int ConfigurationView::findRow(unsigned int col, const std::string& value, unsigned int offsetRow) const
01045 {
01046 for(unsigned int row=offsetRow; row<theDataView_.size(); ++row)
01047 {
01048 if(theDataView_[row][col] == value)
01049 return row;
01050 }
01051
01052 __SS__ << "\tIn view: " << tableName_
01053 << ", Can't find value=" << value
01054 << " in column named " << columnsInfo_[col].getName()
01055 << " with type=" << columnsInfo_[col].getType()
01056 << std::endl;
01057
01058
01059
01060 throw std::runtime_error(ss.str());
01061 }
01062
01063
01064 unsigned int ConfigurationView::findRowInGroup(unsigned int col, const std::string& value,
01065 const std::string &groupId, const std::string &childLinkIndex, unsigned int offsetRow) const
01066 {
01067 unsigned int groupIdCol = getColLinkGroupID(childLinkIndex);
01068 for(unsigned int row=offsetRow; row<theDataView_.size(); ++row)
01069 {
01070 if(theDataView_[row][col] == value &&
01071 isEntryInGroupCol(row,groupIdCol,groupId))
01072 return row;
01073 }
01074
01075 __SS__ << "\tIn view: " << tableName_ << ", Can't find in group the value=" <<
01076 value << " in column named " <<
01077 columnsInfo_[col].getName() << " with type=" <<
01078 columnsInfo_[col].getType() << " and GroupID: " <<
01079 groupId << " in column " << groupIdCol <<
01080 " with GroupID child link index " << childLinkIndex << std::endl;
01081 __MOUT__ << "\n" << ss.str();
01082 throw std::runtime_error(ss.str());
01083 }
01084
01085
01086
01087
01088 unsigned int ConfigurationView::findCol(const std::string& name) const
01089 {
01090 for(unsigned int col=0; col<columnsInfo_.size(); ++col)
01091 if(columnsInfo_[col].getName() == name)
01092 return col;
01093
01094 __SS__ << "\tIn view: " << tableName_ <<
01095 ", Can't find column named " << name << std::endl;
01096 throw std::runtime_error(ss.str());
01097 }
01098
01099
01100
01101
01102 unsigned int ConfigurationView::findColByType(const std::string& type, int startingCol) const
01103 {
01104 for(unsigned int col=startingCol; col<columnsInfo_.size(); ++col)
01105 if(columnsInfo_[col].getType() == type)
01106 return col;
01107
01108 return INVALID;
01109 }
01110
01111
01112
01113 const std::string& ConfigurationView::getUniqueStorageIdentifier(void) const
01114 {
01115 return uniqueStorageIdentifier_;
01116 }
01117
01118
01119 const std::string& ConfigurationView::getTableName(void) const
01120 {
01121 return tableName_;
01122 }
01123
01124
01125 const ConfigurationVersion& ConfigurationView::getVersion(void) const
01126 {
01127 return version_;
01128 }
01129
01130
01131 const std::string& ConfigurationView::getComment(void) const
01132 {
01133 return comment_;
01134 }
01135
01136
01137 const std::string& ConfigurationView::getAuthor(void) const
01138 {
01139 return author_;
01140 }
01141
01142
01143 const time_t& ConfigurationView::getCreationTime(void) const
01144 {
01145 return creationTime_;
01146 }
01147
01148
01149 const time_t& ConfigurationView::getLastAccessTime(void) const
01150 {
01151 return lastAccessTime_;
01152 }
01153
01154
01155 const bool& ConfigurationView::getLooseColumnMatching(void) const
01156 {
01157 return fillWithLooseColumnMatching_;
01158 }
01159
01160
01161
01162 const unsigned int ConfigurationView::getDataColumnSize(void) const
01163 {
01164
01165 if(!getNumberOfRows()) return getNumberOfColumns();
01166 return theDataView_[0].size();
01167 }
01168
01169
01170
01171
01172 const unsigned int& ConfigurationView::getSourceColumnMismatch(void) const
01173 {
01174 return sourceColumnMismatchCount_;
01175 }
01176
01177
01178
01179
01180 const unsigned int& ConfigurationView::getSourceColumnMissing(void) const
01181 {
01182 return sourceColumnMissingCount_;
01183 }
01184
01185
01186
01187
01188 const std::set<std::string>& ConfigurationView::getSourceColumnNames(void) const
01189 {
01190 return sourceColumnNames_;
01191 }
01192
01193
01194 std::set<std::string> ConfigurationView::getColumnNames(void) const
01195 {
01196 std::set<std::string> retSet;
01197 for(auto &colInfo: columnsInfo_)
01198 retSet.emplace(colInfo.getName());
01199 return retSet;
01200 }
01201
01202
01203 std::set<std::string> ConfigurationView::getColumnStorageNames(void) const
01204 {
01205 std::set<std::string> retSet;
01206 for(auto &colInfo: columnsInfo_)
01207 retSet.emplace(colInfo.getStorageName());
01208 return retSet;
01209 }
01210
01211
01212 std::vector<std::string> ConfigurationView::getDefaultRowValues(void) const
01213 {
01214 std::vector<std::string> retVec;
01215
01216
01217 for(unsigned int col=0;col<getNumberOfColumns();++col)
01218 retVec.push_back(columnsInfo_[col].getDefaultValue());
01219
01220 return retVec;
01221 }
01222
01223
01224 unsigned int ConfigurationView::getNumberOfRows(void) const
01225 {
01226 return theDataView_.size();
01227 }
01228
01229
01230 unsigned int ConfigurationView::getNumberOfColumns(void) const
01231 {
01232 return columnsInfo_.size();
01233 }
01234
01235
01236 const ConfigurationView::DataView& ConfigurationView::getDataView(void) const
01237 {
01238 return theDataView_;
01239 }
01240
01241
01242
01243
01244
01245
01246
01247
01248 const std::vector<ViewColumnInfo>& ConfigurationView::getColumnsInfo (void) const
01249 {
01250 return columnsInfo_;
01251 }
01252
01253
01254 std::vector<ViewColumnInfo>* ConfigurationView::getColumnsInfoP(void)
01255 {
01256 return &columnsInfo_;
01257 }
01258
01259 const ViewColumnInfo& ConfigurationView::getColumnInfo(unsigned int column) const
01260 {
01261 if(column >= columnsInfo_.size())
01262 {
01263 std::stringstream errMsg;
01264 errMsg << __COUT_HDR_FL__ << "\nCan't find column " << column <<
01265 "\n\n\n\nThe column info is likely missing due to incomplete Configuration View filling.\n\n"
01266 << std::endl;
01267 throw std::runtime_error(errMsg.str().c_str());
01268 }
01269 return columnsInfo_[column];
01270 }
01271
01272
01273
01274 void ConfigurationView::setUniqueStorageIdentifier(const std::string &storageUID)
01275 {
01276 uniqueStorageIdentifier_ = storageUID;
01277 }
01278
01279
01280 void ConfigurationView::setTableName(const std::string &name)
01281 {
01282 tableName_ = name;
01283 }
01284
01285
01286 void ConfigurationView::setComment(const std::string &comment)
01287 {
01288 comment_ = comment;
01289 }
01290
01291
01292 void ConfigurationView::setURIEncodedComment(const std::string &uriComment)
01293 {
01294 comment_ = decodeURIComponent(uriComment);
01295 }
01296
01297
01298 void ConfigurationView::setAuthor(const std::string &author)
01299 {
01300 author_ = author;
01301 }
01302
01303
01304 void ConfigurationView::setCreationTime(time_t t)
01305 {
01306 creationTime_ = t;
01307 }
01308
01309
01310 void ConfigurationView::setLastAccessTime(time_t t)
01311 {
01312 lastAccessTime_ = t;
01313 }
01314
01315
01316 void ConfigurationView::setLooseColumnMatching(bool setValue)
01317 {
01318 fillWithLooseColumnMatching_ = setValue;
01319 }
01320
01321
01322 void ConfigurationView::reset (void)
01323 {
01324 version_ = -1;
01325 comment_ = "";
01326 author_ + "";
01327 columnsInfo_.clear();
01328 theDataView_.clear();
01329 }
01330
01331
01332 void ConfigurationView::print (std::ostream &out) const
01333 {
01334 out << "==============================================================================" << std::endl;
01335 out << "Print: " << tableName_ << " Version: " << version_ << " Comment: " << comment_ <<
01336 " Author: " << author_ << " Creation Time: " << ctime(&creationTime_) << std::endl;
01337 out << "\t\tNumber of Cols " << getNumberOfColumns() << std::endl;
01338 out << "\t\tNumber of Rows " << getNumberOfRows() << std::endl;
01339
01340 out << "Columns:\t";
01341 for(int i=0;i<(int)columnsInfo_.size();++i)
01342 out << i << ":" << columnsInfo_[i].getName() << ":" << columnsInfo_[i].getStorageName() << ":" << columnsInfo_[i].getDataType() << "\t ";
01343 out << std::endl;
01344
01345 out << "Rows:" << std::endl;
01346 int num;
01347 std::string val;
01348 for(int r=0;r<(int)getNumberOfRows();++r)
01349 {
01350 out << r << ":\t";
01351 for(int c=0;c<(int)getNumberOfColumns();++c)
01352 {
01353 out << c << ":";
01354
01355
01356 if(columnsInfo_[c].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
01357 {
01358 int choiceIndex = -1;
01359 std::vector<std::string> choices = columnsInfo_[c].getDataChoices();
01360 val = convertEnvVariables(theDataView_[r][c]);
01361
01362 if(val == columnsInfo_[c].getDefaultValue())
01363 choiceIndex = 0;
01364 else
01365 {
01366 for(int i=0;i<(int)choices.size();++i)
01367 if(val == choices[i])
01368 choiceIndex = i+1;
01369 }
01370
01371 out << "ChoiceIndex=" << choiceIndex << ":";
01372 }
01373
01374
01375 out << theDataView_[r][c];
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388 out << "\t\t";
01389 }
01390 out << std::endl;
01391 }
01392 }
01393
01394
01395
01396 void ConfigurationView::printJSON (std::ostream &out) const
01397 {
01398 out << "{\n";
01399 out << "\"NAME\" : \"" << tableName_ << "\",\n";
01400
01401
01402
01403 out << "\"COMMENT\" : ";
01404
01405
01406 std::string val;
01407 val = comment_;
01408 out << "\"";
01409 for(unsigned int i=0;i<val.size();++i)
01410 {
01411
01412 if(val[i] == '\n')
01413 out << "\\n";
01414 else if(val[i] == '\t')
01415 out << "\\t";
01416 else if(val[i] == '\r')
01417 out << "\\r";
01418 else
01419 {
01420
01421 if(val[i] == '"' ||
01422 val[i] == '\\')
01423 out << '\\';
01424 out << val[i];
01425 }
01426 }
01427 out << "\",\n";
01428
01429 out << "\"AUTHOR\" : \"" << author_ << "\",\n";
01430 out << "\"CREATION_TIME\" : " << creationTime_ << ",\n";
01431
01432
01433
01434
01435
01436
01437 out << "\"COL_TYPES\" : {\n";
01438 for(int c=0;c<(int)getNumberOfColumns();++c)
01439 {
01440 out << "\t\t\"" << columnsInfo_[c].getStorageName() << "\" : ";
01441 out << "\"" << columnsInfo_[c].getDataType() << "\"";
01442 if(c+1 < (int)getNumberOfColumns())
01443 out << ",";
01444 out << "\n";
01445 }
01446 out << "},\n";
01447
01448 out << "\"DATA_SET\" : [\n";
01449 int num;
01450 for(int r=0;r<(int)getNumberOfRows();++r)
01451 {
01452 out << "\t{\n";
01453 for(int c=0;c<(int)getNumberOfColumns();++c)
01454 {
01455 out << "\t\t\"" << columnsInfo_[c].getStorageName() << "\" : ";
01456
01457 out << "\"" << getEscapedValueAsString(r,c,false) << "\"";
01458
01459 if(c+1 < (int)getNumberOfColumns())
01460 out << ",";
01461 out << "\n";
01462 }
01463 out << "\t}";
01464 if(r+1 < (int)getNumberOfRows())
01465 out << ",";
01466 out << "\n";
01467 }
01468 out << "]\n";
01469
01470 out << "}";
01471 }
01472
01473
01474
01475
01476 std::string restoreJSONStringEntities(const std::string &str)
01477 {
01478 unsigned int sz = str.size();
01479 if(!sz) return "";
01480
01481 std::stringstream retStr;
01482 unsigned int i=0;
01483 for(;i<sz-1;++i)
01484 {
01485 if(str[i] == '\\')
01486 switch(str[i+1])
01487 {
01488 case 'n':
01489 retStr << '\n'; ++i; break;
01490 case '"':
01491 retStr << '"'; ++i; break;
01492 case 't':
01493 retStr << '\t'; ++i; break;
01494 case 'r':
01495 retStr << '\r'; ++i; break;
01496 case '\\':
01497 retStr << '\\'; ++i; break;
01498 default:
01499 retStr << str[i];
01500 }
01501 else
01502 retStr << str[i];
01503 }
01504 if(i == sz-1)
01505 retStr << str[sz-1];
01506
01507 return retStr.str();
01508 }
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519 int ConfigurationView::fillFromJSON(const std::string &json)
01520 {
01521 std::vector<std::string> keys;
01522 keys.push_back ("NAME");
01523 keys.push_back ("COMMENT");
01524 keys.push_back ("AUTHOR");
01525 keys.push_back ("CREATION_TIME");
01526
01527 keys.push_back ("DATA_SET");
01528 enum {
01529 CV_JSON_FILL_NAME,
01530 CV_JSON_FILL_COMMENT,
01531 CV_JSON_FILL_AUTHOR,
01532 CV_JSON_FILL_CREATION_TIME,
01533
01534 CV_JSON_FILL_DATA_SET
01535 };
01536
01537
01538
01539 sourceColumnMismatchCount_ = 0;
01540 sourceColumnMissingCount_ = 0;
01541 sourceColumnNames_.clear();
01542 unsigned int colFoundCount = 0;
01543 unsigned int i = 0;
01544 unsigned int row = -1;
01545 unsigned int colSpeedup = 0;
01546 unsigned int startString, startNumber, endNumber = -1;
01547 unsigned int bracketCount = 0;
01548 unsigned int sqBracketCount = 0;
01549 bool inQuotes = 0;
01550 bool newString = 0;
01551 bool newValue = 0;
01552 bool isDataArray = 0;
01553 bool keyIsMatch, keyIsComment;
01554 unsigned int keyIsMatchIndex, keyIsMatchStorageIndex, keyIsMatchCommentIndex;
01555 const std::string COMMENT_ALT_KEY = "COMMENT";
01556
01557 std::string extractedString = "", currKey = "", currVal = "";
01558 unsigned int currDepth;
01559
01560 std::vector<std::string> jsonPath;
01561 std::vector<char> jsonPathType;
01562 char lastPopType = '_';
01563
01564 unsigned int matchedKey = -1;
01565 unsigned int lastCol = -1;
01566
01567
01568
01569 for(;i<json.size();++i)
01570 {
01571 switch(json[i])
01572 {
01573 case '"':
01574 if(i-1 < json.size() &&
01575 json[i-1] == '\\') break;
01576
01577 inQuotes = !inQuotes;
01578 if(inQuotes)
01579 startString = i;
01580 else
01581 {
01582 extractedString = restoreJSONStringEntities(
01583 json.substr(startString+1,i-startString-1));
01584 newString = 1;
01585 }
01586 break;
01587 case ':':
01588 if(inQuotes) break;
01589
01590
01591 if(jsonPathType[jsonPathType.size()-1] != '{'
01592 || !newString)
01593 {
01594 __MOUT__ << "Invalid ':' position" << std::endl;
01595 return -1;
01596 }
01597
01598
01599 jsonPathType.push_back('K');
01600 jsonPath.push_back(extractedString);
01601 startNumber = i;
01602 newString = 0;
01603 endNumber = -1;
01604 break;
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616 case ',':
01617 if(inQuotes) break;
01618 if(lastPopType == '{')
01619 {
01620
01621 if(jsonPathType[jsonPathType.size()-1] == 'K')
01622 {
01623 lastPopType = 'K';
01624 jsonPath.pop_back();
01625 jsonPathType.pop_back();
01626 }
01627 break;
01628 }
01629
01630 if(newString)
01631 currVal = extractedString;
01632 else
01633 {
01634 if(endNumber == (unsigned int)-1 ||
01635 endNumber <= startNumber)
01636 endNumber = i;
01637
01638 if(endNumber <= startNumber)
01639 currVal = "";
01640 else
01641 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
01642 }
01643
01644 currDepth = bracketCount;
01645
01646 if(jsonPathType[jsonPathType.size()-1] == 'K')
01647 {
01648 currKey = jsonPath[jsonPathType.size()-1];
01649 newValue = 1;
01650
01651
01652 lastPopType = 'K';
01653 jsonPath.pop_back();
01654 jsonPathType.pop_back();
01655 }
01656 else if(jsonPathType[jsonPathType.size()-1] == '[')
01657 {
01658
01659 for(unsigned int k=jsonPathType.size()-2; k<jsonPathType.size(); --k)
01660 if(jsonPathType[k] == 'K')
01661 {
01662 currKey = jsonPath[k];
01663 break;
01664 }
01665 else if(k == 0)
01666 {
01667 __MOUT__ << "Invalid array position" << std::endl;
01668 return -1;
01669 }
01670
01671 newValue = 1;
01672 isDataArray = 1;
01673 }
01674 else
01675 {
01676 __MOUT__ << "Invalid ',' position" << std::endl;
01677 return -1;
01678 }
01679
01680 startNumber = i;
01681 break;
01682
01683 case '{':
01684 if(inQuotes) break;
01685 lastPopType = '_';
01686 jsonPathType.push_back('{');
01687 jsonPath.push_back("{");
01688 ++bracketCount;
01689 break;
01690
01691
01692
01693
01694
01695
01696 case '}':
01697 if(inQuotes) break;
01698
01699 if(lastPopType != '{' &&
01700 jsonPathType[jsonPathType.size()-1] == 'K')
01701 {
01702 currDepth = bracketCount;
01703 currKey = jsonPath[jsonPathType.size()-1];
01704 if(newString)
01705 currVal = extractedString;
01706 else
01707 {
01708 if(endNumber == (unsigned int)-1 ||
01709 endNumber <= startNumber)
01710 endNumber = i;
01711
01712 if(endNumber <= startNumber)
01713 currVal = "";
01714 else
01715 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
01716 }
01717 newValue = 1;
01718
01719 jsonPath.pop_back();
01720 jsonPathType.pop_back();
01721 }
01722
01723 if(jsonPathType[jsonPathType.size()-1] != '{')
01724 {
01725 __MOUT__ << "Invalid '}' position" << std::endl;
01726 return -1;
01727 }
01728 lastPopType = '{';
01729 jsonPath.pop_back();
01730 jsonPathType.pop_back();
01731 --bracketCount;
01732 break;
01733 case '[':
01734 if(inQuotes) break;
01735 jsonPathType.push_back('[');
01736 jsonPath.push_back("[");
01737 ++sqBracketCount;
01738 startNumber = i;
01739 break;
01740 case ']':
01741 if(inQuotes) break;
01742
01743
01744 if(jsonPathType[jsonPathType.size()-1] != '[')
01745 {
01746 __MOUT__ << "Invalid ']' position" << std::endl;
01747 return -1;
01748 }
01749
01750 currDepth = bracketCount;
01751
01752
01753 if(newString)
01754 currVal = extractedString;
01755 else
01756 {
01757 if(endNumber == (unsigned int)-1 ||
01758 endNumber <= startNumber)
01759 endNumber = i;
01760
01761 if(endNumber <= startNumber)
01762 currVal = "";
01763 else
01764 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
01765 }
01766 isDataArray = 1;
01767
01768
01769 for(unsigned int k=jsonPathType.size()-2; k<jsonPathType.size(); --k)
01770 if(jsonPathType[k] == 'K')
01771 {
01772 currKey = jsonPath[k];
01773 break;
01774 }
01775 else if(k == 0)
01776 {
01777 __MOUT__ << "Invalid array position" << std::endl;
01778 return -1;
01779 }
01780
01781
01782 if(jsonPathType[jsonPathType.size()-1] != '[')
01783 {
01784 __MOUT__ << "Invalid ']' position" << std::endl;
01785 return -1;
01786 }
01787 lastPopType = '[';
01788 jsonPath.pop_back();
01789 jsonPathType.pop_back();
01790 --sqBracketCount;
01791 break;
01792 case ' ':
01793 case '\t':
01794 case '\n':
01795 case '\r':
01796 if(inQuotes) break;
01797 if(startNumber != (unsigned int)-1 &&
01798 endNumber == (unsigned int)-1)
01799 endNumber = i;
01800 startNumber = i;
01801 break;
01802 default:;
01803 }
01804
01805 if(0)
01806 {
01807 std::cout << i << ":\t" << json[i] << " - ";
01808
01809 std::cout << "ExtKey=";
01810 for(unsigned int k=0;k<jsonPath.size();++k)
01811 std::cout << jsonPath[k] << "/";
01812 std::cout << " - ";
01813 std::cout << lastPopType << " ";
01814 std::cout << bracketCount << " ";
01815 std::cout << sqBracketCount << " ";
01816 std::cout << inQuotes << " ";
01817 std::cout << newValue << "-";
01818 std::cout << currKey << "-{" << currDepth << "}:" ;
01819 std::cout << currVal << " ";
01820 std::cout << startNumber << "-";
01821 std::cout << endNumber << " ";
01822 std::cout << "\n";
01823 }
01824
01825
01826
01827
01828 if(newValue)
01829 {
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852 matchedKey = -1;
01853 for(unsigned int k=0;k<keys.size();++k)
01854 if((currDepth == 1 && keys[k] == currKey) ||
01855 (currDepth > 1 && keys[k] == jsonPath[1]))
01856 matchedKey = k;
01857
01858 if(matchedKey != (unsigned int)-1)
01859 {
01860
01861
01862
01863 switch(matchedKey)
01864 {
01865 case CV_JSON_FILL_NAME:
01866 if(currDepth == 1) setTableName(currVal);
01867 break;
01868 case CV_JSON_FILL_COMMENT:
01869 if(currDepth == 1) setComment(currVal);
01870 break;
01871 case CV_JSON_FILL_AUTHOR:
01872 if(currDepth == 1) setAuthor(currVal);
01873 break;
01874 case CV_JSON_FILL_CREATION_TIME:
01875 if(currDepth == 1) setCreationTime(strtol(currVal.c_str(),0,10));
01876 break;
01877
01878
01879
01880 case CV_JSON_FILL_DATA_SET:
01881
01882
01883
01884
01885 if(currDepth == 2)
01886 {
01887
01888
01889 unsigned int col, ccnt = 0;
01890 unsigned int noc = getNumberOfColumns();
01891 for(;ccnt<noc;++ccnt)
01892 {
01893
01894
01895
01896
01897 if(fillWithLooseColumnMatching_)
01898 {
01899
01900
01901
01902
01903 col = colSpeedup;
01904
01905
01906 if(col <= lastCol)
01907 row = addRow();
01908 lastCol = col;
01909 if(getNumberOfRows() == 1)
01910 sourceColumnNames_.emplace(currKey);
01911
01912
01913
01914 if(row >= getNumberOfRows())
01915 {
01916 __SS__ << "Invalid row" << std::endl;
01917 std::cout << ss.str();
01918 throw std::runtime_error(ss.str());
01919 return -1;
01920 }
01921
01922 theDataView_[row][col] = currVal;
01923 break;
01924 }
01925 else
01926 {
01927 col = (ccnt + colSpeedup) % noc;
01928
01929
01930
01931
01932 keyIsMatch = true;
01933 keyIsComment = true;
01934 for(keyIsMatchIndex=0, keyIsMatchStorageIndex=0, keyIsMatchCommentIndex=0;
01935 keyIsMatchIndex<currKey.size();++keyIsMatchIndex)
01936 {
01937 if(columnsInfo_[col].getStorageName()[keyIsMatchStorageIndex] == '_')
01938 ++keyIsMatchStorageIndex;
01939 if(currKey[keyIsMatchIndex] == '_')
01940 continue;
01941
01942
01943 if(keyIsMatchStorageIndex >= columnsInfo_[col].getStorageName().size() ||
01944 currKey[keyIsMatchIndex] !=
01945 columnsInfo_[col].getStorageName()[keyIsMatchStorageIndex])
01946 {
01947
01948 keyIsMatch = false;
01949 if(!keyIsComment)
01950 break;
01951 }
01952
01953
01954 if(keyIsComment && keyIsMatchCommentIndex < COMMENT_ALT_KEY.size())
01955 {
01956 if(currKey[keyIsMatchIndex] != COMMENT_ALT_KEY[keyIsMatchCommentIndex])
01957 {
01958
01959 keyIsComment = false;
01960 }
01961 }
01962
01963 ++keyIsMatchStorageIndex;
01964 }
01965
01966 if(keyIsMatch || keyIsComment)
01967 {
01968
01969 if(col <= lastCol)
01970 {
01971 if(getNumberOfRows())
01972 sourceColumnMissingCount_ += getNumberOfColumns() - colFoundCount;
01973
01974 colFoundCount = 0;
01975 row = addRow();
01976 }
01977 lastCol = col;
01978 ++colFoundCount;
01979
01980 if(getNumberOfRows() == 1)
01981 sourceColumnNames_.emplace(currKey);
01982
01983
01984
01985 if(row >= getNumberOfRows())
01986 {
01987 __SS__ << "Invalid row" << std::endl;
01988 __MOUT__ << "\n" << ss.str();
01989 throw std::runtime_error(ss.str());
01990 return -1;
01991 }
01992
01993 theDataView_[row][col] = currVal;
01994 break;
01995 }
01996 }
01997 }
01998
01999 colSpeedup = (colSpeedup + 1) % noc;
02000
02001 if(ccnt >= getNumberOfColumns())
02002 {
02003 __SS__ << "\n\nInvalid column in JSON source data: " <<
02004 currKey << " not found in column names of table named " <<
02005 getTableName() << "." <<
02006 std::endl;
02007 __MOUT__ << "\n" << ss.str();
02008
02009
02010 ++sourceColumnMismatchCount_;
02011 if(getNumberOfRows() == 1)
02012 sourceColumnNames_.emplace(currKey);
02013
02014
02015
02016 }
02017
02018 }
02019 break;
02020 default:;
02021 }
02022
02023 }
02024
02025
02026
02027 newString = 0;
02028 newValue = 0;
02029 isDataArray = 0;
02030 endNumber = -1;
02031 }
02032
02033
02034 }
02035
02036
02037
02038
02039
02040 return 0;
02041 }
02042
02043
02044
02045
02046 bool ConfigurationView::isURIEncodedCommentTheSame(const std::string &comment) const
02047 {
02048 std::string compareStr = decodeURIComponent(comment);
02049 return comment_ == compareStr;
02050 }
02051
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104 int ConfigurationView::fillFromCSV(const std::string &data, const int &dataOffset,
02105 const std::string &author)
02106 throw(std::runtime_error)
02107 {
02108 int r = dataOffset;
02109 int c = 0;
02110
02111 int i = 0;
02112 int j = data.find(',',i);
02113 int k = data.find(';',i);
02114
02115 bool rowWasModified;
02116 unsigned int countRowsModified = 0;
02117 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
02118 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
02119
02120
02121 while(k != (int)(std::string::npos))
02122 {
02123 rowWasModified = false;
02124 if(r >= (int)getNumberOfRows())
02125 {
02126 addRow();
02127
02128 rowWasModified = true;
02129 }
02130
02131 while(j < k && j != (int)(std::string::npos))
02132 {
02133
02134
02135
02136 if(c >= (int)getNumberOfColumns()-2)
02137 {
02138 i=j+1;
02139 j = data.find(',',i);
02140 ++c;
02141 continue;
02142 }
02143
02144 if(setURIEncodedValue(data.substr(i,j-i),r,c))
02145 rowWasModified = true;
02146
02147 i=j+1;
02148 j = data.find(',',i);
02149 ++c;
02150 }
02151
02152
02153 if(author != "" && rowWasModified)
02154 {
02155 __MOUT__ << "Row=" << r << " was modified!" << std::endl;
02156 setValue(author,r,authorCol);
02157 setValue(time(0),r,timestampCol);
02158 }
02159
02160 if(rowWasModified) ++countRowsModified;
02161
02162 ++r;
02163 c = 0;
02164
02165
02166 i = k+1;
02167 j = data.find(',',i);
02168 k = data.find(';',i);
02169 }
02170
02171
02172 while(r < (int)getNumberOfRows())
02173 {
02174 deleteRow(r);
02175 __MOUT__ << "Row deleted: " << r << std::endl;
02176 ++countRowsModified;
02177 }
02178
02179 __MOUT_INFO__ << "countRowsModified=" <<
02180 countRowsModified << std::endl;
02181
02182 if(!countRowsModified)
02183 {
02184 __SS__ << "No rows were modified! No reason to fill a view with same content." << std::endl;
02185 __MOUT__ << "\n" << ss.str();
02186 return -1;
02187 }
02188
02189
02190
02191
02192 sourceColumnNames_.clear();
02193 for(unsigned int i=0;i<getNumberOfColumns();++i)
02194 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
02195
02196 init();
02197
02198
02199
02200
02201
02202
02203 return 0;
02204 }
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214 bool ConfigurationView::setURIEncodedValue(const std::string &value, const unsigned int &r,
02215 const unsigned int &c, const std::string &author)
02216 {
02217 if(!(c < columnsInfo_.size() && r < getNumberOfRows()))
02218 {
02219 __SS__ << "Invalid row (" << r << ") col (" << c << ") requested!" << std::endl;
02220 throw std::runtime_error(ss.str());
02221 }
02222
02223 std::string valueStr = decodeURIComponent(value);
02224 std::string originalValueStr = getValueAsString(r,c,false);
02225
02226
02227
02228
02229
02230 if(columnsInfo_[c].getDataType() == ViewColumnInfo::DATATYPE_NUMBER)
02231 {
02232
02233 std::string convertedString = convertEnvVariables(valueStr);
02234 if(!isNumber(convertedString))
02235 {
02236 __SS__ << "\tIn configuration " << tableName_
02237 << " at column=" << columnsInfo_[c].getName()
02238 << " the value set (" << convertedString << ")"
02239 << " is not a number! Please fix it or change the column type..." << std::endl;
02240 throw std::runtime_error(ss.str());
02241 }
02242 theDataView_[r][c] = valueStr;
02243 }
02244 else if(columnsInfo_[c].getDataType() == ViewColumnInfo::DATATYPE_TIME)
02245 {
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256 setValue(time_t(strtol(valueStr.c_str(),0,10)),
02257 r,c);
02258 }
02259 else
02260 theDataView_[r][c] = valueStr;
02261
02262 bool rowWasModified = (originalValueStr != getValueAsString(r,c,false));
02263
02264
02265 if(author != "" && rowWasModified)
02266 {
02267 __MOUT__ << "Row=" << r << " was modified!" << std::endl;
02268 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
02269 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
02270 setValue(author,r,authorCol);
02271 setValue(time(0),r,timestampCol);
02272 }
02273
02274 return rowWasModified;
02275 }
02276
02277
02278
02279
02280 std::string ConfigurationView::decodeURIComponent(const std::string &data)
02281 {
02282 std::string decodeURIString(data.size(),0);
02283 unsigned int j=0;
02284 for(unsigned int i=0;i<data.size();++i,++j)
02285 {
02286 if(data[i] == '%')
02287 {
02288
02289 if(data[i+1] > '9')
02290 decodeURIString[j] += (data[i+1]-55)*16;
02291 else
02292 decodeURIString[j] += (data[i+1]-48)*16;
02293
02294
02295 if(data[i+2] > '9')
02296 decodeURIString[j] += (data[i+2]-55);
02297 else
02298 decodeURIString[j] += (data[i+2]-48);
02299
02300 i+=2;
02301 }
02302 else
02303 decodeURIString[j] = data[i];
02304 }
02305 decodeURIString.resize(j);
02306 return decodeURIString;
02307 }
02308
02309
02310 void ConfigurationView::resizeDataView(unsigned int nRows, unsigned int nCols)
02311 {
02312
02313 theDataView_.resize(nRows, std::vector<std::string>(nCols));
02314 }
02315
02316
02317
02318
02319
02320 int ConfigurationView::addRow (const std::string &author)
02321 {
02322 int row = getNumberOfRows();
02323 theDataView_.resize(getNumberOfRows()+1,std::vector<std::string>(getNumberOfColumns()));
02324
02325 std::vector<std::string> defaultRowValues =
02326 getDefaultRowValues();
02327
02328
02329 for(unsigned int col=0;col<getNumberOfColumns();++col)
02330 theDataView_[row][col] = defaultRowValues[col];
02331
02332 if(author != "")
02333 {
02334 __MOUT__ << "Row=" << row << " was created!" << std::endl;
02335 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
02336 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
02337 setValue(author,row,authorCol);
02338 setValue(time(0),row,timestampCol);
02339 }
02340
02341 return row;
02342 }
02343
02344
02345
02346
02347 void ConfigurationView::deleteRow(int r)
02348 {
02349 if(r >= (int)getNumberOfRows())
02350 {
02351
02352 __SS__ << "Row " << r << " is out of bounds (Row Count = " <<
02353 getNumberOfRows() << ") and can not be deleted." <<
02354 std::endl;
02355 throw std::runtime_error(ss.str());
02356 }
02357
02358 theDataView_.erase(theDataView_.begin()+r);
02359 }
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375 const bool ConfigurationView::getChildLink(const unsigned int& c, bool& isGroup,
02376 std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>& linkPair) const
02377 {
02378
02379 if(!(c < columnsInfo_.size()))
02380 {
02381 __SS__ << "Invalid col (" << c << ") requested!" << std::endl;
02382 throw std::runtime_error(ss.str());
02383 }
02384
02385
02386
02387
02388
02389 if((isGroup = columnsInfo_[c].isChildLinkGroupID()) ||
02390 columnsInfo_[c].isChildLinkUID())
02391 {
02392
02393
02394 linkPair.second = c;
02395 std::string index = columnsInfo_[c].getChildLinkIndex();
02396
02397
02398
02399
02400 for(unsigned int col=0; col<columnsInfo_.size(); ++col)
02401 {
02402
02403 if(col == c) continue;
02404 else if(columnsInfo_[col].isChildLink() &&
02405 index == columnsInfo_[col].getChildLinkIndex())
02406 {
02407
02408 __MOUT__ << "getChildLink Found match for col: " << c << " at " << col << std::endl;
02409 linkPair.first = col;
02410 return true;
02411 }
02412 }
02413
02414
02415 __SS__ << "\tIn view: " << tableName_ <<
02416 ", Can't find complete child link for column name " << columnsInfo_[c].getName() << std::endl;
02417 throw std::runtime_error(ss.str());
02418 }
02419
02420 if(!columnsInfo_[c].isChildLink())
02421 return false;
02422
02423
02424 linkPair.first = c;
02425 std::string index = columnsInfo_[c].getChildLinkIndex();
02426
02427
02428
02429
02430 for(unsigned int col=0; col<columnsInfo_.size(); ++col)
02431 {
02432
02433 if(col == c) continue;
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445 if(((columnsInfo_[col].isChildLinkUID() && !(isGroup = false)) ||
02446 (columnsInfo_[col].isChildLinkGroupID() && (isGroup = true)))
02447 && index == columnsInfo_[col].getChildLinkIndex())
02448 {
02449
02450
02451 linkPair.second = col;
02452 return true;
02453 }
02454 }
02455
02456
02457 __SS__ << "\tIn view: " << tableName_ <<
02458 ", Can't find complete child link id for column name " << columnsInfo_[c].getName() << std::endl;
02459 throw std::runtime_error(ss.str());
02460 }
02461
02462
02463
02464
02465 bool ConfigurationView::isNumber(const std::string& s) const
02466 {
02467
02468 if(s.find("0x") == 0)
02469 {
02470
02471 for(unsigned int i=2;i<s.size();++i)
02472 {
02473 if(!((s[i] >= '0' && s[i] <= '9') ||
02474 (s[i] >= 'A' && s[i] <= 'F') ||
02475 (s[i] >= 'a' && s[i] <= 'f')
02476 ))
02477 {
02478
02479 return false;
02480 }
02481 }
02482
02483 }
02484 else if(s[0] == 'b')
02485 {
02486
02487
02488 for(unsigned int i=1;i<s.size();++i)
02489 {
02490 if(!((s[i] >= '0' && s[i] <= '1')
02491 ))
02492 {
02493
02494 return false;
02495 }
02496 }
02497 }
02498 else
02499 {
02500
02501 for(unsigned int i=0;i<s.size();++i)
02502 if(!((s[i] >= '0' && s[i] <= '9') ||
02503 s[i] == '.' ||
02504 s[i] == '+' ||
02505 s[i] == '-'))
02506 return false;
02507
02508
02509 }
02510
02511 return true;
02512 }
02513
02514
02515
02516
02517 #ifdef __GNUG__
02518 #include <cstdlib>
02519 #include <memory>
02520 #include <cxxabi.h>
02521
02522 std::string ots_demangle(const char* name) {
02523
02524 int status = -4;
02525
02526
02527 std::unique_ptr<char, void(*)(void*)> res {
02528 abi::__cxa_demangle(name, NULL, NULL, &status),
02529 std::free
02530 };
02531
02532 return (status==0) ? res.get() : name ;
02533 }
02534
02535 #else
02536
02537
02538 std::string ots_demangle(const char* name) {
02539 return name;
02540 }
02541
02542
02543 #endif