1 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationView.h"
11 #define __MF_SUBJECT__ "ConfigurationView"
13 #define __MF_HDR__ tableName_ << ":v" << version_ << ":" << __COUT_HDR_FL__
15 const unsigned int ConfigurationView::INVALID = -1;
18 ConfigurationView::ConfigurationView(
const std::string &name)
19 : uniqueStorageIdentifier_ (
""),
24 creationTime_ (time(0)),
27 fillWithLooseColumnMatching_(false),
28 sourceColumnMismatchCount_ (0),
29 sourceColumnMissingCount_ (0)
33 ConfigurationView::~ConfigurationView(
void)
42 __SS__ <<
"Invalid use of operator=... Should not directly copy a ConfigurationView. Please use ConfigurationView::copy(sourceView,author,comment)";
43 throw std::runtime_error(ss.str());
49 const std::string &author)
51 tableName_ = src.tableName_;
52 version_ = destinationVersion;
53 comment_ = src.comment_;
56 lastAccessTime_ = time(0);
57 columnsInfo_ = src.columnsInfo_;
58 theDataView_ = src.theDataView_;
59 sourceColumnNames_ = src.sourceColumnNames_;
71 void ConfigurationView::init(
void)
77 std::set<std::string> colNameSet;
78 std::string capsColName, colName;
79 for(
auto &colInfo: columnsInfo_)
81 colName = colInfo.getStorageName();
82 if(colName ==
"COMMENT_DESCRIPTION")
85 for(
unsigned int i=0;i<colName.size(); ++i)
87 if(colName[i] ==
'_')
continue;
88 capsColName += colName[i];
91 colNameSet.emplace(capsColName);
94 if(colNameSet.size() != columnsInfo_.size())
96 __SS__ <<
"Configuration Error:\t" <<
97 " Columns names must be unique! There are " << columnsInfo_.size() <<
98 " columns and the unique name count is " << colNameSet.size() << std::endl;
99 __MOUT_ERR__ <<
"\n" << ss.str();
101 throw std::runtime_error(ss.str());
108 if((colPos = findColByType(ViewColumnInfo::TYPE_COMMENT)) != INVALID)
110 if(columnsInfo_[colPos].getName() !=
"CommentDescription")
112 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
113 " data type column must have name=" <<
114 "CommentDescription" << std::endl;
115 __MOUT_ERR__ <<
"\n" << ss.str();
116 throw std::runtime_error(ss.str());
119 if(findColByType(ViewColumnInfo::TYPE_COMMENT,colPos+1) != INVALID)
121 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
122 " data type in column " <<
123 columnsInfo_[colPos].getName() <<
124 " is repeated. This is not allowed." << std::endl;
125 __MOUT_ERR__ <<
"\n" << ss.str();
126 throw std::runtime_error(ss.str());
129 if(colPos != getNumberOfColumns()-3)
131 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
132 " data type column must be 3rd to last (in column " <<
133 getNumberOfColumns()-3 <<
")." << std::endl;
134 __MOUT_ERR__ <<
"\n" << ss.str();
135 throw std::runtime_error(ss.str());
140 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
141 " data type column " <<
" is missing. This is not allowed." << std::endl;
142 __MOUT_ERR__ <<
"\n" << ss.str();
143 throw std::runtime_error(ss.str());
147 if((colPos = findColByType(ViewColumnInfo::TYPE_AUTHOR)) != INVALID)
149 if(findColByType(ViewColumnInfo::TYPE_AUTHOR,colPos+1) != INVALID)
151 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_AUTHOR <<
152 " data type in column " <<
153 columnsInfo_[colPos].getName() <<
154 " is repeated. This is not allowed." << std::endl;
155 __MOUT_ERR__ <<
"\n" << ss.str();
156 throw std::runtime_error(ss.str());
159 if(colPos != getNumberOfColumns()-2)
161 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_AUTHOR <<
162 " data type column must be 2nd to last (in column " <<
163 getNumberOfColumns()-2 <<
")." << std::endl;
164 __MOUT_ERR__ <<
"\n" << ss.str();
165 throw std::runtime_error(ss.str());
170 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_AUTHOR <<
171 " data type column " <<
" is missing. This is not allowed." << std::endl;
172 __MOUT_ERR__ <<
"\n" << ss.str();
173 throw std::runtime_error(ss.str());
177 if((colPos = findColByType(ViewColumnInfo::TYPE_TIMESTAMP)) != INVALID)
179 if(findColByType(ViewColumnInfo::TYPE_TIMESTAMP,colPos+1) != INVALID)
181 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_TIMESTAMP <<
182 " data type in column " <<
183 columnsInfo_[colPos].getName() <<
" is repeated. This is not allowed." <<
185 __MOUT_ERR__ <<
"\n" << ss.str();
186 throw std::runtime_error(ss.str());
189 if(colPos != getNumberOfColumns()-1)
191 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_TIMESTAMP <<
192 " data type column must be last (in column " <<
193 getNumberOfColumns()-1 <<
")." << std::endl;
194 __MOUT_ERR__ <<
"\n" << ss.str();
195 throw std::runtime_error(ss.str());
200 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_TIMESTAMP <<
201 " data type column " <<
" is missing. This is not allowed." << std::endl;
202 __MOUT_ERR__ <<
"\n" << ss.str();
203 throw std::runtime_error(ss.str());
209 std::set<std::string > uidSet;
210 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
212 if(uidSet.find(theDataView_[row][colUID_]) != uidSet.end())
214 __SS__ << (
"Entries in UID are not unique. Specifically at row=" +
215 std::to_string(row) +
" value=" + theDataView_[row][colUID_])<< std::endl;
216 __MOUT_ERR__ <<
"\n" << ss.str();
217 throw std::runtime_error(ss.str());
220 if(theDataView_[row][colUID_].size() == 0)
222 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' " <<
223 " was identified. UIDs must contain at least 1 character." <<
225 throw std::runtime_error(ss.str());
228 for(
unsigned int i=0;i<theDataView_[row][colUID_].size();++i)
230 (theDataView_[row][colUID_][i] >=
'A' && theDataView_[row][colUID_][i] <=
'Z') ||
231 (theDataView_[row][colUID_][i] >=
'a' && theDataView_[row][colUID_][i] <=
'z') ||
232 (theDataView_[row][colUID_][i] >=
'0' && theDataView_[row][colUID_][i] <=
'9') ||
233 (theDataView_[row][colUID_][i] ==
'-' || theDataView_[row][colUID_][i] <=
'_')
236 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' " <<
237 " was identified. UIDs must contain only letters, numbers," <<
238 "dashes, and underscores." << std::endl;
239 throw std::runtime_error(ss.str());
242 uidSet.insert(theDataView_[row][colUID_]);
244 if(uidSet.size() != getNumberOfRows())
246 __SS__ <<
"Entries in UID are not unique!" <<
247 "There are " << getNumberOfRows() <<
248 " rows and the unique UID count is " << uidSet.size() << std::endl;
249 __MOUT_ERR__ <<
"\n" << ss.str();
250 throw std::runtime_error(ss.str());
254 colPos = (
unsigned int)-1;
255 while((colPos = findColByType(ViewColumnInfo::TYPE_UNIQUE_DATA,colPos+1)) != INVALID)
257 std::set<std::string > uDataSet;
258 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
260 if(uDataSet.find(theDataView_[row][colPos]) != uDataSet.end())
262 __SS__ <<
"Entries in Unique Data column " <<
263 columnsInfo_[colPos].getName() <<
264 (
" are not unique. Specifically at row=" +
265 std::to_string(row) +
" value=" + theDataView_[row][colPos]) <<
267 __MOUT_ERR__ <<
"\n" << ss.str();
268 throw std::runtime_error(ss.str());
270 uDataSet.insert(theDataView_[row][colPos]);
272 if(uDataSet.size() != getNumberOfRows())
274 __SS__ <<
"Entries in Unique Data column " <<
275 columnsInfo_[colPos].getName() <<
" are not unique!" <<
276 "There are " << getNumberOfRows() <<
277 " rows and the unique data count is " << uDataSet.size() << std::endl;
278 __MOUT_ERR__ <<
"\n" << ss.str();
279 throw std::runtime_error(ss.str());
283 auto rowDefaults = getDefaultRowValues();
290 std::set<std::string> groupIdIndexes, childLinkIndexes, childLinkIdLabels;
291 unsigned int groupIdIndexesCount = 0, childLinkIndexesCount = 0, childLinkIdLabelsCount = 0;
292 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
294 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
296 const std::vector<std::string>& theDataChoices =
297 columnsInfo_[col].getDataChoices();
300 if(theDataChoices.size() && theDataChoices[0] ==
305 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
309 if(theDataView_[row][col] == rowDefaults[col])
312 for(
const auto &choice:theDataChoices)
314 if(theDataView_[row][col] == choice)
322 __SS__ <<
"Configuration Error:\t'" << theDataView_[row][col] <<
"' in column " <<
323 columnsInfo_[col].getName() <<
" is not a valid Fixed Choice option. " <<
324 "Possible values are as follows: ";
326 for(
unsigned int i = 0; i < columnsInfo_[col].getDataChoices().size(); ++i)
329 ss << columnsInfo_[col].getDataChoices()[i];
331 ss <<
"." << std::endl;
332 __MOUT_ERR__ <<
"\n" << ss.str();
333 throw std::runtime_error(ss.str());
337 if(columnsInfo_[col].isChildLink())
341 const std::vector<std::string>& theDataChoices =
342 columnsInfo_[col].getDataChoices();
345 if(!theDataChoices.size() ||
346 theDataChoices[0] ==
"arbitraryBool=1")
350 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
354 for(
const auto &choice:theDataChoices)
356 if(theDataView_[row][col] == choice)
364 __SS__ <<
"Configuration Error:\t'" << theDataView_[row][col] <<
"' in column " <<
365 columnsInfo_[col].getName() <<
" is not a valid Fixed Choice option. " <<
366 "Possible values are as follows: ";
368 for(
unsigned int i = 0; i < columnsInfo_[col].getDataChoices().size(); ++i)
371 ss << columnsInfo_[col].getDataChoices()[i];
373 ss <<
"." << std::endl;
374 __MOUT_ERR__ <<
"\n" << ss.str();
375 throw std::runtime_error(ss.str());
379 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_ON_OFF)
380 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
382 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" || theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
383 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_ON;
384 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"off" || theDataView_[row][col] ==
"Off" || theDataView_[row][col] ==
"OFF")
385 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_OFF;
388 __SS__ <<
"Configuration Error:\t" << theDataView_[row][col] <<
" in column " <<
389 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;
390 __MOUT_ERR__ <<
"\n" << ss.str();
391 throw std::runtime_error(ss.str());
394 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_TRUE_FALSE)
395 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
397 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" || theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
398 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_TRUE;
399 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"false" || theDataView_[row][col] ==
"False" || theDataView_[row][col] ==
"FALSE")
400 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_FALSE;
403 __SS__ <<
"Configuration Error:\t" << theDataView_[row][col] <<
" in column " <<
404 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;
405 __MOUT_ERR__ <<
"\n" << ss.str();
406 throw std::runtime_error(
"Invalid true/false usage");
409 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_YES_NO)
410 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
412 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" || theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
413 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_YES;
414 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"no" || theDataView_[row][col] ==
"No" || theDataView_[row][col] ==
"NO")
415 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_NO;
418 __SS__ <<
"Configuration Error:\t" << theDataView_[row][col] <<
" in column " <<
419 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;
420 __MOUT_ERR__ <<
"\n" << ss.str();
421 throw std::runtime_error(ss.str());
424 else if(columnsInfo_[col].isGroupID())
426 colLinkGroupIDs_[columnsInfo_[col].getChildLinkIndex()] = col;
428 groupIdIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
429 ++groupIdIndexesCount;
431 else if(columnsInfo_[col].isChildLink())
434 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
435 if(theDataView_[row][col] ==
"NoLink" ||
436 theDataView_[row][col] ==
"No_Link" ||
437 theDataView_[row][col] ==
"NOLINK" ||
438 theDataView_[row][col] ==
"NO_LINK" ||
439 theDataView_[row][col] ==
"Nolink" ||
440 theDataView_[row][col] ==
"nolink" ||
441 theDataView_[row][col] ==
"noLink")
442 theDataView_[row][col] = ViewColumnInfo::DATATYPE_LINK_DEFAULT;
445 childLinkIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
446 ++childLinkIndexesCount;
449 if(columnsInfo_[col].getDataType() != ViewColumnInfo::DATATYPE_STRING)
451 __SS__ <<
"Configuration Error:\t" <<
"Column " << col <<
452 " with name " << columnsInfo_[col].getName() <<
453 " is a Child Link column and has an illegal data type of '" <<
454 columnsInfo_[col].getDataType() <<
455 "'. The data type for Child Link columns must be " <<
456 ViewColumnInfo::DATATYPE_STRING << std::endl;
457 __MOUT_ERR__ <<
"\n" << ss.str();
458 throw std::runtime_error(ss.str());
462 else if(columnsInfo_[col].isChildLinkUID() ||
463 columnsInfo_[col].isChildLinkGroupID())
466 childLinkIdLabels.emplace(columnsInfo_[col].getChildLinkIndex());
467 ++childLinkIdLabelsCount;
470 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
471 if(theDataView_[row][col] ==
"")
472 theDataView_[row][col] = rowDefaults[col];
478 if(groupIdIndexes.size() != groupIdIndexesCount)
480 __SS__ << (
"GroupId Labels are not unique!") <<
481 "There are " << groupIdIndexesCount <<
482 " GroupId Labels and the unique count is " << groupIdIndexes.size() << std::endl;
483 __MOUT_ERR__ <<
"\n" << ss.str();
484 throw std::runtime_error(ss.str());
486 if(childLinkIndexes.size() != childLinkIndexesCount)
488 __SS__ << (
"Child Link Labels are not unique!") <<
489 "There are " << childLinkIndexesCount <<
490 " Child Link Labels and the unique count is " << childLinkIndexes.size() << std::endl;
491 __MOUT_ERR__ <<
"\n" << ss.str();
492 throw std::runtime_error(ss.str());
494 if(childLinkIdLabels.size() != childLinkIdLabelsCount)
496 __SS__ << (
"Child Link ID Labels are not unique!") <<
497 "There are " << childLinkIdLabelsCount <<
498 " Child Link ID Labels and the unique count is " << childLinkIdLabels.size() << std::endl;
499 __MOUT_ERR__ <<
"\n" << ss.str();
500 throw std::runtime_error(ss.str());
506 __MOUT__ <<
"Error occured in ConfigurationView::init() for version=" << version_ << std::endl;
515 void ConfigurationView::getValue(std::string& value,
unsigned int row,
unsigned int col,
bool convertEnvironmentVariables)
const
519 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
521 __SS__ <<
"Invalid row col requested" << std::endl;
522 __MOUT_ERR__ <<
"\n" << ss.str();
523 throw std::runtime_error(ss.str());
526 value = validateValueForColumn(theDataView_[row][col],col,convertEnvironmentVariables);
569 std::string ConfigurationView::validateValueForColumn(
const std::string& value,
unsigned int col,
bool convertEnvironmentVariables)
const
572 if(col >= columnsInfo_.size())
574 __SS__ <<
"Invalid col requested" << std::endl;
575 __MOUT_ERR__ <<
"\n" << ss.str();
576 throw std::runtime_error(ss.str());
579 std::string retValue;
581 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING)
582 retValue = convertEnvironmentVariables?convertEnvVariables(value):value;
583 else if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_TIME)
587 strtol((convertEnvironmentVariables?convertEnvVariables(value):value).c_str(),
590 ::localtime_r(×tamp, &tmstruct);
591 ::strftime(&retValue[0], 30,
"%c %Z", &tmstruct);
592 retValue.resize(strlen(retValue.c_str()));
596 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
597 <<
" in configuration " << tableName_
598 <<
" at column=" << columnsInfo_[col].getName()
599 <<
" for getValue with type '" << ots_demangle(
typeid(retValue).name())
601 __MOUT_ERR__ <<
"\n" << ss.str();
602 throw std::runtime_error(ss.str());
613 std::string ConfigurationView::getValueAsString(
unsigned int row,
unsigned int col,
614 bool convertEnvironmentVariables)
const
616 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
617 throw std::runtime_error(
"Invalid row col requested");
621 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_ON_OFF)
623 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" || theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
624 return ViewColumnInfo::TYPE_VALUE_ON;
626 return ViewColumnInfo::TYPE_VALUE_OFF;
628 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_TRUE_FALSE)
630 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" || theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
631 return ViewColumnInfo::TYPE_VALUE_TRUE;
633 return ViewColumnInfo::TYPE_VALUE_FALSE;
635 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_YES_NO)
637 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" || theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
638 return ViewColumnInfo::TYPE_VALUE_YES;
640 return ViewColumnInfo::TYPE_VALUE_NO;
644 return convertEnvironmentVariables?convertEnvVariables(theDataView_[row][col]):
645 theDataView_[row][col];
655 std::string ConfigurationView::getEscapedValueAsString(
unsigned int row,
unsigned int col,
656 bool convertEnvironmentVariables)
const
658 std::string val = getValueAsString(row,col,convertEnvironmentVariables);
659 std::string retVal =
"";
660 retVal.reserve(val.size());
661 for(
unsigned int i=0;i<val.size();++i)
665 else if(val[i] ==
'\t')
667 else if(val[i] ==
'\r')
682 std::string ConfigurationView::convertEnvVariables(
const std::string& data)
const
684 std::string converted = data;
685 if(data.find(
"${") != std::string::npos)
687 unsigned int begin = data.find(
"${");
688 unsigned int end = data.find(
"}");
689 std::string envVariable = data.substr(begin+2, end-begin-2);
691 if(getenv(envVariable.c_str()) !=
nullptr)
693 return convertEnvVariables(converted.replace(begin,end-begin+1,getenv(envVariable.c_str())));
696 throw std::runtime_error(
"In configuration " + tableName_ +
" the environmental variable: " + envVariable +
" is not set! Please make sure you set it before continuing!");
704 void ConfigurationView::setValue(
const std::string &value,
unsigned int row,
unsigned int col)
706 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
708 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << std::endl;
709 throw std::runtime_error(ss.str());
712 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING)
713 theDataView_[row][col] = value;
717 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
718 <<
" in configuration " << tableName_
719 <<
" at column=" << columnsInfo_[col].getName()
720 <<
" for setValue with type '" << ots_demangle(
typeid(value).name())
722 throw std::runtime_error(ss.str());
725 void ConfigurationView::setValue(
const char *value,
unsigned int row,
unsigned int col)
726 { setValue(std::string(value),row,col); }
731 void ConfigurationView::setValueAsString(
const std::string &value,
unsigned int row,
unsigned int col)
733 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
735 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << std::endl;
736 throw std::runtime_error(ss.str());
739 theDataView_[row][col] = value;
745 const unsigned int ConfigurationView::getOrInitColUID (
void)
747 if(colUID_ != INVALID)
return colUID_;
750 colUID_ = findColByType(ViewColumnInfo::TYPE_UID);
751 if(colUID_ == INVALID)
753 __MOUT__ <<
"Column Types: " << std::endl;
754 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
755 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
756 __SS__ <<
"\tMissing UID Column in table named '" << tableName_ <<
"'" << std::endl;
757 __MOUT_ERR__ <<
"\n" << ss.str() << std::endl;
758 throw std::runtime_error(ss.str());
766 const unsigned int ConfigurationView::getColUID (
void)
const
768 if(colUID_ != INVALID)
return colUID_;
770 __MOUT__ <<
"Column Types: " << std::endl;
771 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
772 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
774 __SS__ << (
"Missing UID Column in config named " + tableName_ +
775 ". (Possibly ConfigurationView was just not initialized?" +
776 "This is the const call so can not alter class members)") << std::endl;
777 __MOUT_ERR__ <<
"\n" << ss.str() << std::endl;
778 throw std::runtime_error(ss.str());
784 void ConfigurationView::addRowToGroup(
const unsigned int &row,
785 const unsigned int &col,
786 const std::string &groupID,
787 const std::string &colDefault)
789 if(isEntryInGroupCol(row,col,groupID))
791 __SS__ <<
"GroupID (" << groupID <<
792 ") added to row (" << row
793 <<
" is already present!" << std::endl;
794 throw std::runtime_error(ss.str());
802 if(getDataView()[row][col] ==
"" ||
803 getDataView()[row][col] == colDefault)
809 groupID +
" | " + getDataView()[row][col],
818 void ConfigurationView::removeRowFromGroup(
const unsigned int &row,
819 const unsigned int &col,
820 const std::string &groupNeedle)
822 __MOUT__ <<
"groupNeedle " << groupNeedle << std::endl;
823 std::set<std::string> groupIDList;
824 if(!isEntryInGroupCol(row,col,groupNeedle,&groupIDList))
826 __SS__ <<
"GroupID (" << groupNeedle <<
827 ") removed from row (" << row
828 <<
") was already removed!" << std::endl;
829 throw std::runtime_error(ss.str());
836 std::string newValue =
"";
837 unsigned int cnt = 0;
838 for(
const auto & groupID : groupIDList)
841 if(groupID == groupNeedle)
continue;
843 if(cnt) newValue +=
" | ";
846 setValue(newValue,row,col);
857 bool ConfigurationView::isEntryInGroup(
const unsigned int &r,
858 const std::string &childLinkIndex,
859 const std::string &groupNeedle)
const
861 unsigned int c = getColLinkGroupID(childLinkIndex);
863 return isEntryInGroupCol(r,c,groupNeedle);
876 bool ConfigurationView::isEntryInGroupCol(
const unsigned int &r,
877 const unsigned int &c,
const std::string &groupNeedle,
878 std::set<std::string> *groupIDList)
const
887 for(;j<theDataView_[r][c].size();++j)
888 if((theDataView_[r][c][j] ==
' ' ||
889 theDataView_[r][c][j] ==
'|')
892 else if((theDataView_[r][c][j] ==
' ' ||
893 theDataView_[r][c][j] ==
'|')
896 if(groupIDList) groupIDList->emplace(theDataView_[r][c].substr(i,j-i));
900 if(groupNeedle == theDataView_[r][c].substr(i,j-i))
912 if(groupIDList) groupIDList->emplace(theDataView_[r][c].substr(i,j-i));
916 if(groupNeedle == theDataView_[r][c].substr(i,j-i))
931 std::set<std::string> ConfigurationView::getSetOfGroupIDs(
const std::string &childLinkIndex,
932 unsigned int r)
const
934 unsigned int c = getColLinkGroupID(childLinkIndex);
938 std::set<std::string> retSet;
943 if(r != (
unsigned int)-1)
945 if(r >= getNumberOfRows())
947 __SS__ <<
"Invalid row requested!" << std::endl;
948 throw std::runtime_error(ss.str());
953 for(;j<theDataView_[r][c].size();++j)
954 if((theDataView_[r][c][j] ==
' ' ||
955 theDataView_[r][c][j] ==
'|')
958 else if((theDataView_[r][c][j] ==
' ' ||
959 theDataView_[r][c][j] ==
'|')
966 retSet.emplace(theDataView_[r][c].substr(i,j-i));
973 retSet.emplace(theDataView_[r][c].substr(i,j-i));
978 for(r=0;r<getNumberOfRows();++r)
987 for(;j<theDataView_[r][c].size();++j)
991 if((theDataView_[r][c][j] ==
' ' ||
992 theDataView_[r][c][j] ==
'|')
995 else if((theDataView_[r][c][j] ==
' ' ||
996 theDataView_[r][c][j] ==
'|')
1002 retSet.emplace(theDataView_[r][c].substr(i,j-i));
1013 retSet.emplace(theDataView_[r][c].substr(i,j-i));
1024 const unsigned int ConfigurationView::getColLinkGroupID(
const std::string &childLinkIndex)
const
1026 std::map<std::string, unsigned int>::const_iterator it = colLinkGroupIDs_.find(childLinkIndex);
1028 colLinkGroupIDs_.end())
1031 __MOUT__ <<
"Existing Column Types: " << std::endl;
1032 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
1033 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
1035 __SS__ << (
"Incompatible table for this group link. Table '" +
1036 tableName_ +
"' is missing a GroupID column with data type '" +
1037 (ViewColumnInfo::TYPE_START_GROUP_ID +
"-" + childLinkIndex) +
1038 "'." ) << std::endl;
1039 __MOUT_ERR__ <<
"\n" << ss.str();
1040 throw std::runtime_error(ss.str());
1044 unsigned int ConfigurationView::findRow(
unsigned int col,
const std::string& value,
unsigned int offsetRow)
const
1046 for(
unsigned int row=offsetRow; row<theDataView_.size(); ++row)
1048 if(theDataView_[row][col] == value)
1052 __SS__ <<
"\tIn view: " << tableName_
1053 <<
", Can't find value=" << value
1054 <<
" in column named " << columnsInfo_[col].getName()
1055 <<
" with type=" << columnsInfo_[col].getType()
1060 throw std::runtime_error(ss.str());
1064 unsigned int ConfigurationView::findRowInGroup(
unsigned int col,
const std::string& value,
1065 const std::string &groupId,
const std::string &childLinkIndex,
unsigned int offsetRow)
const
1067 unsigned int groupIdCol = getColLinkGroupID(childLinkIndex);
1068 for(
unsigned int row=offsetRow; row<theDataView_.size(); ++row)
1070 if(theDataView_[row][col] == value &&
1071 isEntryInGroupCol(row,groupIdCol,groupId))
1075 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find in group the value=" <<
1076 value <<
" in column named " <<
1077 columnsInfo_[col].getName() <<
" with type=" <<
1078 columnsInfo_[col].getType() <<
" and GroupID: " <<
1079 groupId <<
" in column " << groupIdCol <<
1080 " with GroupID child link index " << childLinkIndex << std::endl;
1081 __MOUT__ <<
"\n" << ss.str();
1082 throw std::runtime_error(ss.str());
1088 unsigned int ConfigurationView::findCol(
const std::string& name)
const
1090 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
1091 if(columnsInfo_[col].getName() == name)
1094 __SS__ <<
"\tIn view: " << tableName_ <<
1095 ", Can't find column named " << name << std::endl;
1096 throw std::runtime_error(ss.str());
1102 unsigned int ConfigurationView::findColByType(
const std::string& type,
int startingCol)
const
1104 for(
unsigned int col=startingCol; col<columnsInfo_.size(); ++col)
1105 if(columnsInfo_[col].getType() == type)
1113 const std::string& ConfigurationView::getUniqueStorageIdentifier(
void)
const
1115 return uniqueStorageIdentifier_;
1119 const std::string& ConfigurationView::getTableName(
void)
const
1131 const std::string& ConfigurationView::getComment(
void)
const
1137 const std::string& ConfigurationView::getAuthor(
void)
const
1143 const time_t& ConfigurationView::getCreationTime(
void)
const
1145 return creationTime_;
1149 const time_t& ConfigurationView::getLastAccessTime(
void)
const
1151 return lastAccessTime_;
1155 const bool& ConfigurationView::getLooseColumnMatching(
void)
const
1157 return fillWithLooseColumnMatching_;
1162 const unsigned int ConfigurationView::getDataColumnSize(
void)
const
1165 if(!getNumberOfRows())
return getNumberOfColumns();
1166 return theDataView_[0].size();
1172 const unsigned int& ConfigurationView::getSourceColumnMismatch(
void)
const
1174 return sourceColumnMismatchCount_;
1180 const unsigned int& ConfigurationView::getSourceColumnMissing(
void)
const
1182 return sourceColumnMissingCount_;
1188 const std::set<std::string>& ConfigurationView::getSourceColumnNames(
void)
const
1190 return sourceColumnNames_;
1194 std::set<std::string> ConfigurationView::getColumnNames(
void)
const
1196 std::set<std::string> retSet;
1197 for(
auto &colInfo: columnsInfo_)
1198 retSet.emplace(colInfo.getName());
1203 std::set<std::string> ConfigurationView::getColumnStorageNames(
void)
const
1205 std::set<std::string> retSet;
1206 for(
auto &colInfo: columnsInfo_)
1207 retSet.emplace(colInfo.getStorageName());
1212 std::vector<std::string> ConfigurationView::getDefaultRowValues(
void)
const
1214 std::vector<std::string> retVec;
1217 for(
unsigned int col=0;col<getNumberOfColumns();++col)
1218 retVec.push_back(columnsInfo_[col].getDefaultValue());
1224 unsigned int ConfigurationView::getNumberOfRows(
void)
const
1226 return theDataView_.size();
1230 unsigned int ConfigurationView::getNumberOfColumns(
void)
const
1232 return columnsInfo_.size();
1236 const ConfigurationView::DataView& ConfigurationView::getDataView(
void)
const
1238 return theDataView_;
1248 const std::vector<ViewColumnInfo>& ConfigurationView::getColumnsInfo (
void)
const
1250 return columnsInfo_;
1254 std::vector<ViewColumnInfo>* ConfigurationView::getColumnsInfoP(
void)
1256 return &columnsInfo_;
1259 const ViewColumnInfo& ConfigurationView::getColumnInfo(
unsigned int column)
const
1261 if(column >= columnsInfo_.size())
1263 std::stringstream errMsg;
1264 errMsg << __COUT_HDR_FL__ <<
"\nCan't find column " << column <<
1265 "\n\n\n\nThe column info is likely missing due to incomplete Configuration View filling.\n\n"
1267 throw std::runtime_error(errMsg.str().c_str());
1269 return columnsInfo_[column];
1274 void ConfigurationView::setUniqueStorageIdentifier(
const std::string &storageUID)
1276 uniqueStorageIdentifier_ = storageUID;
1280 void ConfigurationView::setTableName(
const std::string &name)
1286 void ConfigurationView::setComment(
const std::string &comment)
1292 void ConfigurationView::setURIEncodedComment(
const std::string &uriComment)
1294 comment_ = decodeURIComponent(uriComment);
1298 void ConfigurationView::setAuthor(
const std::string &author)
1304 void ConfigurationView::setCreationTime(time_t t)
1310 void ConfigurationView::setLastAccessTime(time_t t)
1312 lastAccessTime_ = t;
1316 void ConfigurationView::setLooseColumnMatching(
bool setValue)
1318 fillWithLooseColumnMatching_ = setValue;
1322 void ConfigurationView::reset (
void)
1327 columnsInfo_.clear();
1328 theDataView_.clear();
1332 void ConfigurationView::print (std::ostream &out)
const
1334 out <<
"==============================================================================" << std::endl;
1335 out <<
"Print: " << tableName_ <<
" Version: " << version_ <<
" Comment: " << comment_ <<
1336 " Author: " << author_ <<
" Creation Time: " << ctime(&creationTime_) << std::endl;
1337 out <<
"\t\tNumber of Cols " << getNumberOfColumns() << std::endl;
1338 out <<
"\t\tNumber of Rows " << getNumberOfRows() << std::endl;
1340 out <<
"Columns:\t";
1341 for(
int i=0;i<(int)columnsInfo_.size();++i)
1342 out << i <<
":" << columnsInfo_[i].getName() <<
":" << columnsInfo_[i].getStorageName() <<
":" << columnsInfo_[i].getDataType() <<
"\t ";
1345 out <<
"Rows:" << std::endl;
1348 for(
int r=0;r<(int)getNumberOfRows();++r)
1351 for(
int c=0;c<(int)getNumberOfColumns();++c)
1356 if(columnsInfo_[c].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
1358 int choiceIndex = -1;
1359 std::vector<std::string> choices = columnsInfo_[c].getDataChoices();
1360 val = convertEnvVariables(theDataView_[r][c]);
1362 if(val == columnsInfo_[c].getDefaultValue())
1366 for(
int i=0;i<(int)choices.size();++i)
1367 if(val == choices[i])
1371 out <<
"ChoiceIndex=" << choiceIndex <<
":";
1375 out << theDataView_[r][c];
1396 void ConfigurationView::printJSON (std::ostream &out)
const
1399 out <<
"\"NAME\" : \"" << tableName_ <<
"\",\n";
1403 out <<
"\"COMMENT\" : ";
1409 for(
unsigned int i=0;i<val.size();++i)
1414 else if(val[i] ==
'\t')
1416 else if(val[i] ==
'\r')
1429 out <<
"\"AUTHOR\" : \"" << author_ <<
"\",\n";
1430 out <<
"\"CREATION_TIME\" : " << creationTime_ <<
",\n";
1437 out <<
"\"COL_TYPES\" : {\n";
1438 for(
int c=0;c<(int)getNumberOfColumns();++c)
1440 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1441 out <<
"\"" << columnsInfo_[c].getDataType() <<
"\"";
1442 if(c+1 < (
int)getNumberOfColumns())
1448 out <<
"\"DATA_SET\" : [\n";
1450 for(
int r=0;r<(int)getNumberOfRows();++r)
1453 for(
int c=0;c<(int)getNumberOfColumns();++c)
1455 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1457 out <<
"\"" << getEscapedValueAsString(r,c,
false) <<
"\"";
1459 if(c+1 < (
int)getNumberOfColumns())
1464 if(r+1 < (
int)getNumberOfRows())
1476 std::string restoreJSONStringEntities(
const std::string &str)
1478 unsigned int sz = str.size();
1481 std::stringstream retStr;
1489 retStr <<
'\n'; ++i;
break;
1491 retStr <<
'"'; ++i;
break;
1493 retStr <<
'\t'; ++i;
break;
1495 retStr <<
'\r'; ++i;
break;
1497 retStr <<
'\\'; ++i;
break;
1505 retStr << str[sz-1];
1507 return retStr.str();
1519 int ConfigurationView::fillFromJSON(
const std::string &json)
1521 std::vector<std::string> keys;
1522 keys.push_back (
"NAME");
1523 keys.push_back (
"COMMENT");
1524 keys.push_back (
"AUTHOR");
1525 keys.push_back (
"CREATION_TIME");
1527 keys.push_back (
"DATA_SET");
1530 CV_JSON_FILL_COMMENT,
1531 CV_JSON_FILL_AUTHOR,
1532 CV_JSON_FILL_CREATION_TIME,
1534 CV_JSON_FILL_DATA_SET
1539 sourceColumnMismatchCount_ = 0;
1540 sourceColumnMissingCount_ = 0;
1541 sourceColumnNames_.clear();
1542 unsigned int colFoundCount = 0;
1544 unsigned int row = -1;
1545 unsigned int colSpeedup = 0;
1546 unsigned int startString, startNumber, endNumber = -1;
1547 unsigned int bracketCount = 0;
1548 unsigned int sqBracketCount = 0;
1552 bool isDataArray = 0;
1553 bool keyIsMatch, keyIsComment;
1554 unsigned int keyIsMatchIndex, keyIsMatchStorageIndex, keyIsMatchCommentIndex;
1555 const std::string COMMENT_ALT_KEY =
"COMMENT";
1557 std::string extractedString =
"", currKey =
"", currVal =
"";
1558 unsigned int currDepth;
1560 std::vector<std::string> jsonPath;
1561 std::vector<char> jsonPathType;
1562 char lastPopType =
'_';
1564 unsigned int matchedKey = -1;
1565 unsigned int lastCol = -1;
1569 for(;i<json.size();++i)
1574 if(i-1 < json.size() &&
1575 json[i-1] ==
'\\')
break;
1577 inQuotes = !inQuotes;
1582 extractedString = restoreJSONStringEntities(
1583 json.substr(startString+1,i-startString-1));
1591 if(jsonPathType[jsonPathType.size()-1] !=
'{'
1594 __MOUT__ <<
"Invalid ':' position" << std::endl;
1599 jsonPathType.push_back(
'K');
1600 jsonPath.push_back(extractedString);
1618 if(lastPopType ==
'{')
1621 if(jsonPathType[jsonPathType.size()-1] ==
'K')
1624 jsonPath.pop_back();
1625 jsonPathType.pop_back();
1631 currVal = extractedString;
1634 if(endNumber == (
unsigned int)-1 ||
1635 endNumber <= startNumber)
1638 if(endNumber <= startNumber)
1641 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
1644 currDepth = bracketCount;
1646 if(jsonPathType[jsonPathType.size()-1] ==
'K')
1648 currKey = jsonPath[jsonPathType.size()-1];
1653 jsonPath.pop_back();
1654 jsonPathType.pop_back();
1656 else if(jsonPathType[jsonPathType.size()-1] ==
'[')
1659 for(
unsigned int k=jsonPathType.size()-2; k<jsonPathType.size(); --k)
1660 if(jsonPathType[k] ==
'K')
1662 currKey = jsonPath[k];
1667 __MOUT__ <<
"Invalid array position" << std::endl;
1676 __MOUT__ <<
"Invalid ',' position" << std::endl;
1686 jsonPathType.push_back(
'{');
1687 jsonPath.push_back(
"{");
1699 if(lastPopType !=
'{' &&
1700 jsonPathType[jsonPathType.size()-1] ==
'K')
1702 currDepth = bracketCount;
1703 currKey = jsonPath[jsonPathType.size()-1];
1705 currVal = extractedString;
1708 if(endNumber == (
unsigned int)-1 ||
1709 endNumber <= startNumber)
1712 if(endNumber <= startNumber)
1715 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
1719 jsonPath.pop_back();
1720 jsonPathType.pop_back();
1723 if(jsonPathType[jsonPathType.size()-1] !=
'{')
1725 __MOUT__ <<
"Invalid '}' position" << std::endl;
1729 jsonPath.pop_back();
1730 jsonPathType.pop_back();
1735 jsonPathType.push_back(
'[');
1736 jsonPath.push_back(
"[");
1744 if(jsonPathType[jsonPathType.size()-1] !=
'[')
1746 __MOUT__ <<
"Invalid ']' position" << std::endl;
1750 currDepth = bracketCount;
1754 currVal = extractedString;
1757 if(endNumber == (
unsigned int)-1 ||
1758 endNumber <= startNumber)
1761 if(endNumber <= startNumber)
1764 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
1769 for(
unsigned int k=jsonPathType.size()-2; k<jsonPathType.size(); --k)
1770 if(jsonPathType[k] ==
'K')
1772 currKey = jsonPath[k];
1777 __MOUT__ <<
"Invalid array position" << std::endl;
1782 if(jsonPathType[jsonPathType.size()-1] !=
'[')
1784 __MOUT__ <<
"Invalid ']' position" << std::endl;
1788 jsonPath.pop_back();
1789 jsonPathType.pop_back();
1797 if(startNumber != (
unsigned int)-1 &&
1798 endNumber == (
unsigned int)-1)
1807 std::cout << i <<
":\t" << json[i] <<
" - ";
1809 std::cout <<
"ExtKey=";
1810 for(
unsigned int k=0;k<jsonPath.size();++k)
1811 std::cout << jsonPath[k] <<
"/";
1813 std::cout << lastPopType <<
" ";
1814 std::cout << bracketCount <<
" ";
1815 std::cout << sqBracketCount <<
" ";
1816 std::cout << inQuotes <<
" ";
1817 std::cout << newValue <<
"-";
1818 std::cout << currKey <<
"-{" << currDepth <<
"}:" ;
1819 std::cout << currVal <<
" ";
1820 std::cout << startNumber <<
"-";
1821 std::cout << endNumber <<
" ";
1853 for(
unsigned int k=0;k<keys.size();++k)
1854 if((currDepth == 1 && keys[k] == currKey) ||
1855 (currDepth > 1 && keys[k] == jsonPath[1]))
1858 if(matchedKey != (
unsigned int)-1)
1865 case CV_JSON_FILL_NAME:
1866 if(currDepth == 1) setTableName(currVal);
1868 case CV_JSON_FILL_COMMENT:
1869 if(currDepth == 1) setComment(currVal);
1871 case CV_JSON_FILL_AUTHOR:
1872 if(currDepth == 1) setAuthor(currVal);
1874 case CV_JSON_FILL_CREATION_TIME:
1875 if(currDepth == 1) setCreationTime(strtol(currVal.c_str(),0,10));
1880 case CV_JSON_FILL_DATA_SET:
1889 unsigned int col, ccnt = 0;
1890 unsigned int noc = getNumberOfColumns();
1891 for(;ccnt<noc;++ccnt)
1897 if(fillWithLooseColumnMatching_)
1909 if(getNumberOfRows() == 1)
1910 sourceColumnNames_.emplace(currKey);
1914 if(row >= getNumberOfRows())
1916 __SS__ <<
"Invalid row" << std::endl;
1917 std::cout << ss.str();
1918 throw std::runtime_error(ss.str());
1922 theDataView_[row][col] = currVal;
1927 col = (ccnt + colSpeedup) % noc;
1933 keyIsComment =
true;
1934 for(keyIsMatchIndex=0, keyIsMatchStorageIndex=0, keyIsMatchCommentIndex=0;
1935 keyIsMatchIndex<currKey.size();++keyIsMatchIndex)
1937 if(columnsInfo_[col].getStorageName()[keyIsMatchStorageIndex] ==
'_')
1938 ++keyIsMatchStorageIndex;
1939 if(currKey[keyIsMatchIndex] ==
'_')
1943 if(keyIsMatchStorageIndex >= columnsInfo_[col].getStorageName().size() ||
1944 currKey[keyIsMatchIndex] !=
1945 columnsInfo_[col].getStorageName()[keyIsMatchStorageIndex])
1954 if(keyIsComment && keyIsMatchCommentIndex < COMMENT_ALT_KEY.size())
1956 if(currKey[keyIsMatchIndex] != COMMENT_ALT_KEY[keyIsMatchCommentIndex])
1959 keyIsComment =
false;
1963 ++keyIsMatchStorageIndex;
1966 if(keyIsMatch || keyIsComment)
1971 if(getNumberOfRows())
1972 sourceColumnMissingCount_ += getNumberOfColumns() - colFoundCount;
1980 if(getNumberOfRows() == 1)
1981 sourceColumnNames_.emplace(currKey);
1985 if(row >= getNumberOfRows())
1987 __SS__ <<
"Invalid row" << std::endl;
1988 __MOUT__ <<
"\n" << ss.str();
1989 throw std::runtime_error(ss.str());
1993 theDataView_[row][col] = currVal;
1999 colSpeedup = (colSpeedup + 1) % noc;
2001 if(ccnt >= getNumberOfColumns())
2003 __SS__ <<
"\n\nInvalid column in JSON source data: " <<
2004 currKey <<
" not found in column names of table named " <<
2005 getTableName() <<
"." <<
2007 __MOUT__ <<
"\n" << ss.str();
2010 ++sourceColumnMismatchCount_;
2011 if(getNumberOfRows() == 1)
2012 sourceColumnNames_.emplace(currKey);
2046 bool ConfigurationView::isURIEncodedCommentTheSame(
const std::string &comment)
const
2048 std::string compareStr = decodeURIComponent(comment);
2049 return comment_ == compareStr;
2104 int ConfigurationView::fillFromCSV(
const std::string &data,
const int &dataOffset,
2105 const std::string &author)
2106 throw(std::runtime_error)
2112 int j = data.find(
',',i);
2113 int k = data.find(
';',i);
2115 bool rowWasModified;
2116 unsigned int countRowsModified = 0;
2117 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
2118 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
2121 while(k != (
int)(std::string::npos))
2123 rowWasModified =
false;
2124 if(r >= (
int)getNumberOfRows())
2128 rowWasModified =
true;
2131 while(j < k && j != (
int)(std::string::npos))
2136 if(c >= (
int)getNumberOfColumns()-2)
2139 j = data.find(
',',i);
2144 if(setURIEncodedValue(data.substr(i,j-i),r,c))
2145 rowWasModified =
true;
2148 j = data.find(
',',i);
2153 if(author !=
"" && rowWasModified)
2155 __MOUT__ <<
"Row=" << r <<
" was modified!" << std::endl;
2156 setValue(author,r,authorCol);
2157 setValue(time(0),r,timestampCol);
2160 if(rowWasModified) ++countRowsModified;
2167 j = data.find(
',',i);
2168 k = data.find(
';',i);
2172 while(r < (
int)getNumberOfRows())
2175 __MOUT__ <<
"Row deleted: " << r << std::endl;
2176 ++countRowsModified;
2179 __MOUT_INFO__ <<
"countRowsModified=" <<
2180 countRowsModified << std::endl;
2182 if(!countRowsModified)
2184 __SS__ <<
"No rows were modified! No reason to fill a view with same content." << std::endl;
2185 __MOUT__ <<
"\n" << ss.str();
2192 sourceColumnNames_.clear();
2193 for(
unsigned int i=0;i<getNumberOfColumns();++i)
2194 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
2214 bool ConfigurationView::setURIEncodedValue(
const std::string &value,
const unsigned int &r,
2215 const unsigned int &c,
const std::string &author)
2217 if(!(c < columnsInfo_.size() && r < getNumberOfRows()))
2219 __SS__ <<
"Invalid row (" << r <<
") col (" << c <<
") requested!" << std::endl;
2220 throw std::runtime_error(ss.str());
2223 std::string valueStr = decodeURIComponent(value);
2224 std::string originalValueStr = getValueAsString(r,c,
false);
2230 if(columnsInfo_[c].getDataType() == ViewColumnInfo::DATATYPE_NUMBER)
2233 std::string convertedString = convertEnvVariables(valueStr);
2234 if(!isNumber(convertedString))
2236 __SS__ <<
"\tIn configuration " << tableName_
2237 <<
" at column=" << columnsInfo_[c].getName()
2238 <<
" the value set (" << convertedString <<
")"
2239 <<
" is not a number! Please fix it or change the column type..." << std::endl;
2240 throw std::runtime_error(ss.str());
2242 theDataView_[r][c] = valueStr;
2244 else if(columnsInfo_[c].getDataType() == ViewColumnInfo::DATATYPE_TIME)
2256 setValue(time_t(strtol(valueStr.c_str(),0,10)),
2260 theDataView_[r][c] = valueStr;
2262 bool rowWasModified = (originalValueStr != getValueAsString(r,c,
false));
2265 if(author !=
"" && rowWasModified)
2267 __MOUT__ <<
"Row=" << r <<
" was modified!" << std::endl;
2268 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
2269 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
2270 setValue(author,r,authorCol);
2271 setValue(time(0),r,timestampCol);
2274 return rowWasModified;
2280 std::string ConfigurationView::decodeURIComponent(
const std::string &data)
2282 std::string decodeURIString(data.size(),0);
2284 for(
unsigned int i=0;i<data.size();++i,++j)
2290 decodeURIString[j] += (data[i+1]-55)*16;
2292 decodeURIString[j] += (data[i+1]-48)*16;
2296 decodeURIString[j] += (data[i+2]-55);
2298 decodeURIString[j] += (data[i+2]-48);
2303 decodeURIString[j] = data[i];
2305 decodeURIString.resize(j);
2306 return decodeURIString;
2310 void ConfigurationView::resizeDataView(
unsigned int nRows,
unsigned int nCols)
2313 theDataView_.resize(nRows, std::vector<std::string>(nCols));
2320 int ConfigurationView::addRow (
const std::string &author)
2322 int row = getNumberOfRows();
2323 theDataView_.resize(getNumberOfRows()+1,std::vector<std::string>(getNumberOfColumns()));
2325 std::vector<std::string> defaultRowValues =
2326 getDefaultRowValues();
2329 for(
unsigned int col=0;col<getNumberOfColumns();++col)
2330 theDataView_[row][col] = defaultRowValues[col];
2334 __MOUT__ <<
"Row=" << row <<
" was created!" << std::endl;
2335 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
2336 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
2337 setValue(author,row,authorCol);
2338 setValue(time(0),row,timestampCol);
2347 void ConfigurationView::deleteRow(
int r)
2349 if(r >= (
int)getNumberOfRows())
2352 __SS__ <<
"Row " << r <<
" is out of bounds (Row Count = " <<
2353 getNumberOfRows() <<
") and can not be deleted." <<
2355 throw std::runtime_error(ss.str());
2358 theDataView_.erase(theDataView_.begin()+r);
2375 const bool ConfigurationView::getChildLink(
const unsigned int& c,
bool& isGroup,
2376 std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>& linkPair)
const
2379 if(!(c < columnsInfo_.size()))
2381 __SS__ <<
"Invalid col (" << c <<
") requested!" << std::endl;
2382 throw std::runtime_error(ss.str());
2389 if((isGroup = columnsInfo_[c].isChildLinkGroupID()) ||
2390 columnsInfo_[c].isChildLinkUID())
2394 linkPair.second = c;
2395 std::string index = columnsInfo_[c].getChildLinkIndex();
2400 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
2403 if(col == c)
continue;
2404 else if(columnsInfo_[col].isChildLink() &&
2405 index == columnsInfo_[col].getChildLinkIndex())
2408 __MOUT__ <<
"getChildLink Found match for col: " << c <<
" at " << col << std::endl;
2409 linkPair.first = col;
2415 __SS__ <<
"\tIn view: " << tableName_ <<
2416 ", Can't find complete child link for column name " << columnsInfo_[c].getName() << std::endl;
2417 throw std::runtime_error(ss.str());
2420 if(!columnsInfo_[c].isChildLink())
2425 std::string index = columnsInfo_[c].getChildLinkIndex();
2430 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
2433 if(col == c)
continue;
2445 if(((columnsInfo_[col].isChildLinkUID() && !(isGroup =
false)) ||
2446 (columnsInfo_[col].isChildLinkGroupID() && (isGroup =
true)))
2447 && index == columnsInfo_[col].getChildLinkIndex())
2451 linkPair.second = col;
2457 __SS__ <<
"\tIn view: " << tableName_ <<
2458 ", Can't find complete child link id for column name " << columnsInfo_[c].getName() << std::endl;
2459 throw std::runtime_error(ss.str());
2465 bool ConfigurationView::isNumber(
const std::string& s)
const
2468 if(s.find(
"0x") == 0)
2471 for(
unsigned int i=2;i<s.size();++i)
2473 if(!((s[i] >=
'0' && s[i] <=
'9') ||
2474 (s[i] >=
'A' && s[i] <=
'F') ||
2475 (s[i] >=
'a' && s[i] <=
'f')
2484 else if(s[0] ==
'b')
2488 for(
unsigned int i=1;i<s.size();++i)
2490 if(!((s[i] >=
'0' && s[i] <=
'1')
2501 for(
unsigned int i=0;i<s.size();++i)
2502 if(!((s[i] >=
'0' && s[i] <=
'9') ||
2522 std::string ots_demangle(
const char* name) {
2527 std::unique_ptr<char, void(*)(void*)> res {
2528 abi::__cxa_demangle(name, NULL, NULL, &status),
2532 return (status==0) ? res.get() : name ;
2538 std::string ots_demangle(
const char* name) {