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