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