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)),
28 fillWithLooseColumnMatching_(false),
29 sourceColumnMismatchCount_ (0),
30 sourceColumnMissingCount_ (0)
34 ConfigurationView::~ConfigurationView(
void)
43 __SS__ <<
"Invalid use of operator=... Should not directly copy a ConfigurationView. Please use ConfigurationView::copy(sourceView,author,comment)";
44 throw std::runtime_error(ss.str());
50 const std::string &author)
52 tableName_ = src.tableName_;
53 version_ = destinationVersion;
54 comment_ = src.comment_;
57 lastAccessTime_ = time(0);
58 columnsInfo_ = src.columnsInfo_;
59 theDataView_ = src.theDataView_;
60 sourceColumnNames_ = src.sourceColumnNames_;
72 void ConfigurationView::init(
void)
78 std::set<std::string> colNameSet;
79 std::string capsColName, colName;
80 for(
auto &colInfo: columnsInfo_)
82 colName = colInfo.getStorageName();
83 if(colName ==
"COMMENT_DESCRIPTION")
86 for(
unsigned int i=0;i<colName.size(); ++i)
88 if(colName[i] ==
'_')
continue;
89 capsColName += colName[i];
92 colNameSet.emplace(capsColName);
95 if(colNameSet.size() != columnsInfo_.size())
97 __SS__ <<
"Configuration Error:\t" <<
98 " Columns names must be unique! There are " << columnsInfo_.size() <<
99 " columns and the unique name count is " << colNameSet.size() << std::endl;
100 __COUT_ERR__ <<
"\n" << ss.str();
102 throw std::runtime_error(ss.str());
108 getOrInitColStatus();
114 if((colPos = findColByType(ViewColumnInfo::TYPE_COMMENT)) != INVALID)
116 if(columnsInfo_[colPos].getName() !=
"CommentDescription")
118 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
119 " data type column must have name=" <<
120 "CommentDescription" << std::endl;
121 __COUT_ERR__ <<
"\n" << ss.str();
122 throw std::runtime_error(ss.str());
125 if(findColByType(ViewColumnInfo::TYPE_COMMENT,colPos+1) != INVALID)
127 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
128 " data type in column " <<
129 columnsInfo_[colPos].getName() <<
130 " is repeated. This is not allowed." << std::endl;
131 __COUT_ERR__ <<
"\n" << ss.str();
132 throw std::runtime_error(ss.str());
135 if(colPos != getNumberOfColumns()-3)
137 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
138 " data type column must be 3rd to last (in column " <<
139 getNumberOfColumns()-3 <<
")." << std::endl;
140 __COUT_ERR__ <<
"\n" << ss.str();
141 throw std::runtime_error(ss.str());
146 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
147 " data type column " <<
" is missing. This is not allowed." << std::endl;
148 __COUT_ERR__ <<
"\n" << ss.str();
149 throw std::runtime_error(ss.str());
153 if((colPos = findColByType(ViewColumnInfo::TYPE_AUTHOR)) != INVALID)
155 if(findColByType(ViewColumnInfo::TYPE_AUTHOR,colPos+1) != INVALID)
157 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_AUTHOR <<
158 " data type in column " <<
159 columnsInfo_[colPos].getName() <<
160 " is repeated. This is not allowed." << std::endl;
161 __COUT_ERR__ <<
"\n" << ss.str();
162 throw std::runtime_error(ss.str());
165 if(colPos != getNumberOfColumns()-2)
167 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_AUTHOR <<
168 " data type column must be 2nd to last (in column " <<
169 getNumberOfColumns()-2 <<
")." << std::endl;
170 __COUT_ERR__ <<
"\n" << ss.str();
171 throw std::runtime_error(ss.str());
176 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_AUTHOR <<
177 " data type column " <<
" is missing. This is not allowed." << std::endl;
178 __COUT_ERR__ <<
"\n" << ss.str();
179 throw std::runtime_error(ss.str());
183 if((colPos = findColByType(ViewColumnInfo::TYPE_TIMESTAMP)) != INVALID)
185 if(findColByType(ViewColumnInfo::TYPE_TIMESTAMP,colPos+1) != INVALID)
187 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_TIMESTAMP <<
188 " data type in column " <<
189 columnsInfo_[colPos].getName() <<
" is repeated. This is not allowed." <<
191 __COUT_ERR__ <<
"\n" << ss.str();
192 throw std::runtime_error(ss.str());
195 if(colPos != getNumberOfColumns()-1)
197 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_TIMESTAMP <<
198 " data type column must be last (in column " <<
199 getNumberOfColumns()-1 <<
")." << std::endl;
200 __COUT_ERR__ <<
"\n" << ss.str();
201 throw std::runtime_error(ss.str());
206 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_TIMESTAMP <<
207 " data type column " <<
" is missing. This is not allowed." << std::endl;
208 __COUT_ERR__ <<
"\n" << ss.str();
209 throw std::runtime_error(ss.str());
215 std::set<std::string > uidSet;
216 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
218 if(uidSet.find(theDataView_[row][colUID_]) != uidSet.end())
220 __SS__ << (
"Entries in UID are not unique. Specifically at row=" +
221 std::to_string(row) +
" value=" + theDataView_[row][colUID_])<< std::endl;
222 __COUT_ERR__ <<
"\n" << ss.str();
223 throw std::runtime_error(ss.str());
226 if(theDataView_[row][colUID_].size() == 0)
228 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' " <<
229 " was identified. UIDs must contain at least 1 character." <<
231 throw std::runtime_error(ss.str());
234 for(
unsigned int i=0;i<theDataView_[row][colUID_].size();++i)
236 (theDataView_[row][colUID_][i] >=
'A' && theDataView_[row][colUID_][i] <=
'Z') ||
237 (theDataView_[row][colUID_][i] >=
'a' && theDataView_[row][colUID_][i] <=
'z') ||
238 (theDataView_[row][colUID_][i] >=
'0' && theDataView_[row][colUID_][i] <=
'9') ||
239 (theDataView_[row][colUID_][i] ==
'-' ||
240 theDataView_[row][colUID_][i] <=
'_')
243 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' " <<
244 " was identified. UIDs must contain only letters, numbers," <<
245 "dashes, and underscores." << std::endl;
246 throw std::runtime_error(ss.str());
249 uidSet.insert(theDataView_[row][colUID_]);
251 if(uidSet.size() != getNumberOfRows())
253 __SS__ <<
"Entries in UID are not unique!" <<
254 "There are " << getNumberOfRows() <<
255 " rows and the unique UID count is " << uidSet.size() << std::endl;
256 __COUT_ERR__ <<
"\n" << ss.str();
257 throw std::runtime_error(ss.str());
261 colPos = (
unsigned int)-1;
262 while((colPos = findColByType(ViewColumnInfo::TYPE_UNIQUE_DATA,colPos+1)) != INVALID)
264 std::set<std::string > uDataSet;
265 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
267 if(uDataSet.find(theDataView_[row][colPos]) != uDataSet.end())
269 __SS__ <<
"Entries in Unique Data column " <<
270 columnsInfo_[colPos].getName() <<
271 (
" are not unique. Specifically at row=" +
272 std::to_string(row) +
" value=" + theDataView_[row][colPos]) <<
274 __COUT_ERR__ <<
"\n" << ss.str();
275 throw std::runtime_error(ss.str());
277 uDataSet.insert(theDataView_[row][colPos]);
279 if(uDataSet.size() != getNumberOfRows())
281 __SS__ <<
"Entries in Unique Data column " <<
282 columnsInfo_[colPos].getName() <<
" are not unique!" <<
283 "There are " << getNumberOfRows() <<
284 " rows and the unique data count is " << uDataSet.size() << std::endl;
285 __COUT_ERR__ <<
"\n" << ss.str();
286 throw std::runtime_error(ss.str());
290 auto rowDefaults = getDefaultRowValues();
297 std::set<std::string> groupIdIndexes, childLinkIndexes, childLinkIdLabels;
298 unsigned int groupIdIndexesCount = 0, childLinkIndexesCount = 0, childLinkIdLabelsCount = 0;
299 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
301 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
303 const std::vector<std::string>& theDataChoices =
304 columnsInfo_[col].getDataChoices();
307 if(theDataChoices.size() && theDataChoices[0] ==
312 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
316 if(theDataView_[row][col] == rowDefaults[col])
319 for(
const auto &choice:theDataChoices)
321 if(theDataView_[row][col] == choice)
329 __SS__ <<
"Configuration Error:\t'" << theDataView_[row][col] <<
"' in column " <<
330 columnsInfo_[col].getName() <<
" is not a valid Fixed Choice option. " <<
331 "Possible values are as follows: ";
333 for(
unsigned int i = 0; i < columnsInfo_[col].getDataChoices().size(); ++i)
336 ss << columnsInfo_[col].getDataChoices()[i];
338 ss <<
"." << std::endl;
339 __COUT_ERR__ <<
"\n" << ss.str();
340 throw std::runtime_error(ss.str());
344 if(columnsInfo_[col].isChildLink())
348 const std::vector<std::string>& theDataChoices =
349 columnsInfo_[col].getDataChoices();
352 if(!theDataChoices.size() ||
353 theDataChoices[0] ==
"arbitraryBool=1")
357 bool skipOne = (theDataChoices.size() &&
358 theDataChoices[0] ==
"arbitraryBool=0");
362 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
367 for(
const auto &choice:theDataChoices)
369 if(skipOne && !hasSkipped) {hasSkipped =
true;
continue;}
371 if(theDataView_[row][col] == choice)
379 __SS__ <<
"Configuration Error:\t'" << theDataView_[row][col] <<
"' in column " <<
380 columnsInfo_[col].getName() <<
" is not a valid Fixed Choice option. " <<
381 "Possible values are as follows: ";
383 for(
unsigned int i = skipOne?1:0; i < columnsInfo_[col].getDataChoices().size(); ++i)
385 if(i == 1 + (skipOne?1:0)) ss <<
", ";
386 ss << columnsInfo_[col].getDataChoices()[i];
388 ss <<
"." << std::endl;
389 __COUT_ERR__ <<
"\n" << ss.str();
390 throw std::runtime_error(ss.str());
394 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_ON_OFF)
395 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
397 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" || theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
398 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_ON;
399 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"off" || theDataView_[row][col] ==
"Off" || theDataView_[row][col] ==
"OFF")
400 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_OFF;
403 __SS__ <<
"Configuration Error:\t" << theDataView_[row][col] <<
" in column " <<
404 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;
405 __COUT_ERR__ <<
"\n" << ss.str();
406 throw std::runtime_error(ss.str());
409 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_TRUE_FALSE)
410 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
412 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" || theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
413 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_TRUE;
414 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"false" || theDataView_[row][col] ==
"False" || theDataView_[row][col] ==
"FALSE")
415 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_FALSE;
418 __SS__ <<
"Configuration Error:\t" << theDataView_[row][col] <<
" in column " <<
419 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;
420 __COUT_ERR__ <<
"\n" << ss.str();
421 throw std::runtime_error(ss.str());
424 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_YES_NO)
425 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
427 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" || theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
428 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_YES;
429 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"no" || theDataView_[row][col] ==
"No" || theDataView_[row][col] ==
"NO")
430 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_NO;
433 __SS__ <<
"Configuration Error:\t" << theDataView_[row][col] <<
" in column " <<
434 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;
435 __COUT_ERR__ <<
"\n" << ss.str();
436 throw std::runtime_error(ss.str());
439 else if(columnsInfo_[col].isGroupID())
441 colLinkGroupIDs_[columnsInfo_[col].getChildLinkIndex()] = col;
443 groupIdIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
444 ++groupIdIndexesCount;
446 else if(columnsInfo_[col].isChildLink())
449 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
450 if(theDataView_[row][col] ==
"NoLink" ||
451 theDataView_[row][col] ==
"No_Link" ||
452 theDataView_[row][col] ==
"NOLINK" ||
453 theDataView_[row][col] ==
"NO_LINK" ||
454 theDataView_[row][col] ==
"Nolink" ||
455 theDataView_[row][col] ==
"nolink" ||
456 theDataView_[row][col] ==
"noLink")
457 theDataView_[row][col] = ViewColumnInfo::DATATYPE_LINK_DEFAULT;
460 childLinkIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
461 ++childLinkIndexesCount;
464 if(columnsInfo_[col].getDataType() != ViewColumnInfo::DATATYPE_STRING)
466 __SS__ <<
"Configuration Error:\t" <<
"Column " << col <<
467 " with name " << columnsInfo_[col].getName() <<
468 " is a Child Link column and has an illegal data type of '" <<
469 columnsInfo_[col].getDataType() <<
470 "'. The data type for Child Link columns must be " <<
471 ViewColumnInfo::DATATYPE_STRING << std::endl;
472 __COUT_ERR__ <<
"\n" << ss.str();
473 throw std::runtime_error(ss.str());
477 else if(columnsInfo_[col].isChildLinkUID() ||
478 columnsInfo_[col].isChildLinkGroupID())
481 childLinkIdLabels.emplace(columnsInfo_[col].getChildLinkIndex());
482 ++childLinkIdLabelsCount;
485 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
486 if(theDataView_[row][col] ==
"")
487 theDataView_[row][col] = rowDefaults[col];
493 if(groupIdIndexes.size() != groupIdIndexesCount)
495 __SS__ << (
"GroupId Labels are not unique!") <<
496 "There are " << groupIdIndexesCount <<
497 " GroupId Labels and the unique count is " << groupIdIndexes.size() << std::endl;
498 __COUT_ERR__ <<
"\n" << ss.str();
499 throw std::runtime_error(ss.str());
501 if(childLinkIndexes.size() != childLinkIndexesCount)
503 __SS__ << (
"Child Link Labels are not unique!") <<
504 "There are " << childLinkIndexesCount <<
505 " Child Link Labels and the unique count is " << childLinkIndexes.size() << std::endl;
506 __COUT_ERR__ <<
"\n" << ss.str();
507 throw std::runtime_error(ss.str());
509 if(childLinkIdLabels.size() != childLinkIdLabelsCount)
511 __SS__ << (
"Child Link ID Labels are not unique!") <<
512 "There are " << childLinkIdLabelsCount <<
513 " Child Link ID Labels and the unique count is " << childLinkIdLabels.size() << std::endl;
514 __COUT_ERR__ <<
"\n" << ss.str();
515 throw std::runtime_error(ss.str());
521 __COUT__ <<
"Error occured in ConfigurationView::init() for version=" << version_ << std::endl;
530 void ConfigurationView::getValue(std::string& value,
unsigned int row,
unsigned int col,
bool convertEnvironmentVariables)
const
534 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
536 __SS__ <<
"Invalid row col requested" << std::endl;
537 __COUT_ERR__ <<
"\n" << ss.str();
538 throw std::runtime_error(ss.str());
541 value = validateValueForColumn(theDataView_[row][col],col,convertEnvironmentVariables);
585 std::string ConfigurationView::validateValueForColumn(
const std::string& value,
586 unsigned int col,
bool convertEnvironmentVariables)
const
589 if(col >= columnsInfo_.size())
591 __SS__ <<
"Invalid col requested" << std::endl;
592 __COUT_ERR__ <<
"\n" << ss.str();
593 throw std::runtime_error(ss.str());
596 std::string retValue;
598 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING)
599 retValue = convertEnvironmentVariables?convertEnvVariables(value):value;
600 else if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_TIME)
604 strtol((convertEnvironmentVariables?convertEnvVariables(value):value).c_str(),
607 ::localtime_r(×tamp, &tmstruct);
608 ::strftime(&retValue[0], 30,
"%c %Z", &tmstruct);
609 retValue.resize(strlen(retValue.c_str()));
613 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
614 <<
" in configuration " << tableName_
615 <<
" at column=" << columnsInfo_[col].getName()
616 <<
" for getValue with type '" << ots_demangle(
typeid(retValue).name())
618 __COUT_ERR__ <<
"\n" << ss.str();
619 throw std::runtime_error(ss.str());
630 std::string ConfigurationView::getValueAsString(
unsigned int row,
unsigned int col,
631 bool convertEnvironmentVariables)
const
633 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
635 __SS__ << (
"Invalid row col requested") << std::endl;
636 __COUT_ERR__ << ss.str();
637 throw std::runtime_error(ss.str());
642 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_ON_OFF)
644 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" || theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
645 return ViewColumnInfo::TYPE_VALUE_ON;
647 return ViewColumnInfo::TYPE_VALUE_OFF;
649 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_TRUE_FALSE)
651 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" || theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
652 return ViewColumnInfo::TYPE_VALUE_TRUE;
654 return ViewColumnInfo::TYPE_VALUE_FALSE;
656 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_YES_NO)
658 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" || theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
659 return ViewColumnInfo::TYPE_VALUE_YES;
661 return ViewColumnInfo::TYPE_VALUE_NO;
665 return convertEnvironmentVariables?convertEnvVariables(theDataView_[row][col]):
666 theDataView_[row][col];
676 std::string ConfigurationView::getEscapedValueAsString(
unsigned int row,
unsigned int col,
677 bool convertEnvironmentVariables)
const
679 std::string val = getValueAsString(row,col,convertEnvironmentVariables);
680 std::string retVal =
"";
681 retVal.reserve(val.size());
682 for(
unsigned int i=0;i<val.size();++i)
686 else if(val[i] ==
'\t')
688 else if(val[i] ==
'\r')
703 std::string ConfigurationView::convertEnvVariables(
const std::string& data)
const
705 std::string converted = data;
706 if(data.find(
"${") != std::string::npos)
708 unsigned int begin = data.find(
"${");
709 unsigned int end = data.find(
"}");
710 std::string envVariable = data.substr(begin+2, end-begin-2);
712 if(getenv(envVariable.c_str()) !=
nullptr)
714 return convertEnvVariables(converted.replace(begin,end-begin+1,getenv(envVariable.c_str())));
718 __SS__ << (
"In configuration " + tableName_ +
" the environmental variable: " + envVariable +
719 " is not set! Please make sure you set it before continuing!") << std::endl;
720 __COUT_ERR__ << ss.str();
721 throw std::runtime_error(ss.str());
730 void ConfigurationView::setValue(
const std::string &value,
unsigned int row,
unsigned int col)
732 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
734 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << std::endl;
735 throw std::runtime_error(ss.str());
738 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING)
739 theDataView_[row][col] = value;
743 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
744 <<
" in configuration " << tableName_
745 <<
" at column=" << columnsInfo_[col].getName()
746 <<
" for setValue with type '" << ots_demangle(
typeid(value).name())
748 throw std::runtime_error(ss.str());
751 void ConfigurationView::setValue(
const char *value,
unsigned int row,
unsigned int col)
752 { setValue(std::string(value),row,col); }
757 void ConfigurationView::setValueAsString(
const std::string &value,
unsigned int row,
unsigned int col)
759 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
761 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << std::endl;
762 throw std::runtime_error(ss.str());
765 theDataView_[row][col] = value;
771 const unsigned int ConfigurationView::getOrInitColUID(
void)
773 if(colUID_ != INVALID)
return colUID_;
776 colUID_ = findColByType(ViewColumnInfo::TYPE_UID);
777 if(colUID_ == INVALID)
779 __COUT__ <<
"Column Types: " << std::endl;
780 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
781 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
782 __SS__ <<
"\tMissing UID Column in table named '" << tableName_ <<
"'" << std::endl;
783 __COUT_ERR__ <<
"\n" << ss.str() << std::endl;
784 throw std::runtime_error(ss.str());
792 const unsigned int ConfigurationView::getColUID(
void)
const
794 if(colUID_ != INVALID)
return colUID_;
796 __COUT__ <<
"Column Types: " << std::endl;
797 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
798 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
800 __SS__ << (
"Missing UID Column in config named " + tableName_ +
801 ". (Possibly ConfigurationView was just not initialized?" +
802 "This is the const call so can not alter class members)") << std::endl;
803 __COUT_ERR__ <<
"\n" << ss.str() << std::endl;
804 throw std::runtime_error(ss.str());
810 const unsigned int ConfigurationView::getOrInitColStatus(
void)
812 if(colStatus_ != INVALID)
return colStatus_;
815 colStatus_ = findCol(ViewColumnInfo::COL_NAME_STATUS);
816 if(colStatus_ == INVALID)
818 __SS__ <<
"\tMissing Status Column in table named '" << tableName_ <<
"'" << std::endl;
819 ss <<
"Column Types: " << std::endl;
820 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
821 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
824 throw std::runtime_error(ss.str());
832 const unsigned int ConfigurationView::getColStatus(
void)
const
834 if(colStatus_ != INVALID)
return colStatus_;
836 __COUT__ <<
"Column Types: " << std::endl;
837 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
838 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
840 __SS__ << (
"Missing Status Column in config named " + tableName_ +
841 ". (Possibly ConfigurationView was just not initialized?" +
842 "This is the const call so can not alter class members)") << std::endl;
843 __COUT_ERR__ <<
"\n" << ss.str() << std::endl;
844 throw std::runtime_error(ss.str());
850 void ConfigurationView::addRowToGroup(
const unsigned int &row,
851 const unsigned int &col,
852 const std::string &groupID)
855 if(isEntryInGroupCol(row,col,groupID))
857 __SS__ <<
"GroupID (" << groupID <<
858 ") added to row (" << row
859 <<
" is already present!" << std::endl;
860 throw std::runtime_error(ss.str());
868 if(getDataView()[row][col] ==
"" ||
869 getDataView()[row][col] == getDefaultRowValues()[col])
875 groupID +
" | " + getDataView()[row][col],
886 bool ConfigurationView::removeRowFromGroup(
const unsigned int &row,
887 const unsigned int &col,
888 const std::string &groupNeedle,
889 bool deleteRowIfNoGroupLeft)
891 __COUT__ <<
"groupNeedle " << groupNeedle << std::endl;
892 std::set<std::string> groupIDList;
893 if(!isEntryInGroupCol(row,col,groupNeedle,&groupIDList))
895 __SS__ <<
"GroupID (" << groupNeedle <<
896 ") removed from row (" << row
897 <<
") was already removed!" << std::endl;
898 throw std::runtime_error(ss.str());
905 std::string newValue =
"";
906 unsigned int cnt = 0;
907 for(
const auto & groupID : groupIDList)
910 if(groupID == groupNeedle)
continue;
912 if(cnt) newValue +=
" | ";
916 bool wasDeleted =
false;
917 if(deleteRowIfNoGroupLeft && newValue ==
"")
919 __COUT__ <<
"Delete row since it no longer part of any group." << std::endl;
924 setValue(newValue,row,col);
937 bool ConfigurationView::isEntryInGroup(
const unsigned int &r,
938 const std::string &childLinkIndex,
939 const std::string &groupNeedle)
const
941 unsigned int c = getColLinkGroupID(childLinkIndex);
943 return isEntryInGroupCol(r,c,groupNeedle);
956 bool ConfigurationView::isEntryInGroupCol(
const unsigned int &r,
957 const unsigned int &c,
const std::string &groupNeedle,
958 std::set<std::string> *groupIDList)
const
967 for(;j<theDataView_[r][c].size();++j)
968 if((theDataView_[r][c][j] ==
' ' ||
969 theDataView_[r][c][j] ==
'|')
972 else if((theDataView_[r][c][j] ==
' ' ||
973 theDataView_[r][c][j] ==
'|')
976 if(groupIDList) groupIDList->emplace(theDataView_[r][c].substr(i,j-i));
980 if(groupNeedle == theDataView_[r][c].substr(i,j-i))
992 if(groupIDList) groupIDList->emplace(theDataView_[r][c].substr(i,j-i));
996 if(groupNeedle == theDataView_[r][c].substr(i,j-i))
1011 std::set<std::string> ConfigurationView::getSetOfGroupIDs(
const std::string &childLinkIndex,
1012 unsigned int r)
const
1014 unsigned int c = getColLinkGroupID(childLinkIndex);
1018 std::set<std::string> retSet;
1023 if(r != (
unsigned int)-1)
1025 if(r >= getNumberOfRows())
1027 __SS__ <<
"Invalid row requested!" << std::endl;
1028 throw std::runtime_error(ss.str());
1033 for(;j<theDataView_[r][c].size();++j)
1034 if((theDataView_[r][c][j] ==
' ' ||
1035 theDataView_[r][c][j] ==
'|')
1038 else if((theDataView_[r][c][j] ==
' ' ||
1039 theDataView_[r][c][j] ==
'|')
1046 retSet.emplace(theDataView_[r][c].substr(i,j-i));
1053 retSet.emplace(theDataView_[r][c].substr(i,j-i));
1058 for(r=0;r<getNumberOfRows();++r)
1067 for(;j<theDataView_[r][c].size();++j)
1071 if((theDataView_[r][c][j] ==
' ' ||
1072 theDataView_[r][c][j] ==
'|')
1075 else if((theDataView_[r][c][j] ==
' ' ||
1076 theDataView_[r][c][j] ==
'|')
1082 retSet.emplace(theDataView_[r][c].substr(i,j-i));
1093 retSet.emplace(theDataView_[r][c].substr(i,j-i));
1104 const unsigned int ConfigurationView::getColLinkGroupID(
const std::string &childLinkIndex)
const
1106 std::map<std::string, unsigned int>::const_iterator it = colLinkGroupIDs_.find(childLinkIndex);
1108 colLinkGroupIDs_.end())
1111 __COUT__ <<
"Existing Column Types: " << std::endl;
1112 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
1113 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
1115 __SS__ << (
"Incompatible table for this group link. Table '" +
1116 tableName_ +
"' is missing a GroupID column with data type '" +
1117 (ViewColumnInfo::TYPE_START_GROUP_ID +
"-" + childLinkIndex) +
1118 "'." ) << std::endl;
1119 __COUT_ERR__ <<
"\n" << ss.str();
1120 throw std::runtime_error(ss.str());
1124 unsigned int ConfigurationView::findRow(
unsigned int col,
const std::string& value,
unsigned int offsetRow)
const
1126 for(
unsigned int row=offsetRow; row<theDataView_.size(); ++row)
1128 if(theDataView_[row][col] == value)
1132 __SS__ <<
"\tIn view: " << tableName_
1133 <<
", Can't find value=" << value
1134 <<
" in column named " << columnsInfo_[col].getName()
1135 <<
" with type=" << columnsInfo_[col].getType()
1140 throw std::runtime_error(ss.str());
1144 unsigned int ConfigurationView::findRowInGroup(
unsigned int col,
const std::string& value,
1145 const std::string &groupId,
const std::string &childLinkIndex,
unsigned int offsetRow)
const
1147 unsigned int groupIdCol = getColLinkGroupID(childLinkIndex);
1148 for(
unsigned int row=offsetRow; row<theDataView_.size(); ++row)
1150 if(theDataView_[row][col] == value &&
1151 isEntryInGroupCol(row,groupIdCol,groupId))
1155 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find in group the value=" <<
1156 value <<
" in column named '" <<
1157 columnsInfo_[col].getName() <<
"' with type=" <<
1158 columnsInfo_[col].getType() <<
" and GroupID: '" <<
1159 groupId <<
"' in column '" << groupIdCol <<
1160 "' with GroupID child link index '" << childLinkIndex <<
"'" << std::endl;
1164 throw std::runtime_error(ss.str());
1170 unsigned int ConfigurationView::findCol(
const std::string& name)
const
1172 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
1173 if(columnsInfo_[col].getName() == name)
1176 __SS__ <<
"\tIn view: " << tableName_ <<
1177 ", Can't find column named '" << name <<
"'" << std::endl;
1178 ss <<
"Existing columns:\n";
1179 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
1180 ss <<
"\t" << columnsInfo_[col].getName() <<
"\n";
1181 throw std::runtime_error(ss.str());
1187 unsigned int ConfigurationView::findColByType(
const std::string& type,
int startingCol)
const
1189 for(
unsigned int col=startingCol; col<columnsInfo_.size(); ++col)
1190 if(columnsInfo_[col].getType() == type)
1198 const std::string& ConfigurationView::getUniqueStorageIdentifier(
void)
const
1200 return uniqueStorageIdentifier_;
1204 const std::string& ConfigurationView::getTableName(
void)
const
1216 const std::string& ConfigurationView::getComment(
void)
const
1222 const std::string& ConfigurationView::getAuthor(
void)
const
1228 const time_t& ConfigurationView::getCreationTime(
void)
const
1230 return creationTime_;
1234 const time_t& ConfigurationView::getLastAccessTime(
void)
const
1236 return lastAccessTime_;
1240 const bool& ConfigurationView::getLooseColumnMatching(
void)
const
1242 return fillWithLooseColumnMatching_;
1247 const unsigned int ConfigurationView::getDataColumnSize(
void)
const
1250 if(!getNumberOfRows())
return getNumberOfColumns();
1251 return theDataView_[0].size();
1257 const unsigned int& ConfigurationView::getSourceColumnMismatch(
void)
const
1259 return sourceColumnMismatchCount_;
1265 const unsigned int& ConfigurationView::getSourceColumnMissing(
void)
const
1267 return sourceColumnMissingCount_;
1273 const std::set<std::string>& ConfigurationView::getSourceColumnNames(
void)
const
1275 return sourceColumnNames_;
1279 std::set<std::string> ConfigurationView::getColumnNames(
void)
const
1281 std::set<std::string> retSet;
1282 for(
auto &colInfo: columnsInfo_)
1283 retSet.emplace(colInfo.getName());
1288 std::set<std::string> ConfigurationView::getColumnStorageNames(
void)
const
1290 std::set<std::string> retSet;
1291 for(
auto &colInfo: columnsInfo_)
1292 retSet.emplace(colInfo.getStorageName());
1297 std::vector<std::string> ConfigurationView::getDefaultRowValues(
void)
const
1299 std::vector<std::string> retVec;
1302 for(
unsigned int col=0;col<getNumberOfColumns();++col)
1309 if(columnsInfo_[col].isChildLink())
1311 const std::vector<std::string>& theDataChoices =
1312 columnsInfo_[col].getDataChoices();
1315 if(!theDataChoices.size() ||
1316 theDataChoices[0] ==
"arbitraryBool=1")
1317 retVec.push_back(columnsInfo_[col].getDefaultValue());
1320 bool skipOne = (theDataChoices.size() &&
1321 theDataChoices[0] ==
"arbitraryBool=0");
1326 bool foundDefault =
false;
1328 for(
const auto &choice:theDataChoices)
1329 if(skipOne && !hasSkipped) {hasSkipped =
true;
continue;}
1330 else if(choice == columnsInfo_[col].getDefaultValue())
1332 foundDefault =
true;
1337 if(!foundDefault && theDataChoices.size() > (skipOne?1:0))
1338 retVec.push_back(theDataChoices[(skipOne?1:0)]);
1340 retVec.push_back(columnsInfo_[col].getDefaultValue());
1344 retVec.push_back(columnsInfo_[col].getDefaultValue());
1351 unsigned int ConfigurationView::getNumberOfRows(
void)
const
1353 return theDataView_.size();
1357 unsigned int ConfigurationView::getNumberOfColumns(
void)
const
1359 return columnsInfo_.size();
1363 const ConfigurationView::DataView& ConfigurationView::getDataView(
void)
const
1365 return theDataView_;
1375 const std::vector<ViewColumnInfo>& ConfigurationView::getColumnsInfo (
void)
const
1377 return columnsInfo_;
1381 std::vector<ViewColumnInfo>* ConfigurationView::getColumnsInfoP(
void)
1383 return &columnsInfo_;
1386 const ViewColumnInfo& ConfigurationView::getColumnInfo(
unsigned int column)
const
1388 if(column >= columnsInfo_.size())
1390 std::stringstream errMsg;
1391 errMsg << __COUT_HDR_FL__ <<
"\nCan't find column " << column <<
1392 "\n\n\n\nThe column info is likely missing due to incomplete Configuration View filling.\n\n"
1394 throw std::runtime_error(errMsg.str().c_str());
1396 return columnsInfo_[column];
1401 void ConfigurationView::setUniqueStorageIdentifier(
const std::string &storageUID)
1403 uniqueStorageIdentifier_ = storageUID;
1407 void ConfigurationView::setTableName(
const std::string &name)
1413 void ConfigurationView::setComment(
const std::string &comment)
1419 void ConfigurationView::setURIEncodedComment(
const std::string &uriComment)
1421 comment_ = decodeURIComponent(uriComment);
1425 void ConfigurationView::setAuthor(
const std::string &author)
1431 void ConfigurationView::setCreationTime(time_t t)
1437 void ConfigurationView::setLastAccessTime(time_t t)
1439 lastAccessTime_ = t;
1443 void ConfigurationView::setLooseColumnMatching(
bool setValue)
1445 fillWithLooseColumnMatching_ = setValue;
1449 void ConfigurationView::reset (
void)
1454 columnsInfo_.clear();
1455 theDataView_.clear();
1459 void ConfigurationView::print (std::ostream &out)
const
1461 out <<
"==============================================================================" << std::endl;
1462 out <<
"Print: " << tableName_ <<
" Version: " << version_ <<
" Comment: " << comment_ <<
1463 " Author: " << author_ <<
" Creation Time: " << ctime(&creationTime_) << std::endl;
1464 out <<
"\t\tNumber of Cols " << getNumberOfColumns() << std::endl;
1465 out <<
"\t\tNumber of Rows " << getNumberOfRows() << std::endl;
1467 out <<
"Columns:\t";
1468 for(
int i=0;i<(int)columnsInfo_.size();++i)
1469 out << i <<
":" << columnsInfo_[i].getName() <<
":" << columnsInfo_[i].getStorageName() <<
":" << columnsInfo_[i].getDataType() <<
"\t ";
1472 out <<
"Rows:" << std::endl;
1475 for(
int r=0;r<(int)getNumberOfRows();++r)
1477 out << (int)r <<
":\t";
1478 for(
int c=0;c<(int)getNumberOfColumns();++c)
1480 out << (int)c <<
":";
1483 if(columnsInfo_[c].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
1485 int choiceIndex = -1;
1486 std::vector<std::string> choices = columnsInfo_[c].getDataChoices();
1487 val = convertEnvVariables(theDataView_[r][c]);
1489 if(val == columnsInfo_[c].getDefaultValue())
1493 for(
int i=0;i<(int)choices.size();++i)
1494 if(val == choices[i])
1498 out <<
"ChoiceIndex=" << choiceIndex <<
":";
1502 out << theDataView_[r][c];
1523 void ConfigurationView::printJSON (std::ostream &out)
const
1526 out <<
"\"NAME\" : \"" << tableName_ <<
"\",\n";
1530 out <<
"\"COMMENT\" : ";
1536 for(
unsigned int i=0;i<val.size();++i)
1541 else if(val[i] ==
'\t')
1543 else if(val[i] ==
'\r')
1556 out <<
"\"AUTHOR\" : \"" << author_ <<
"\",\n";
1557 out <<
"\"CREATION_TIME\" : " << creationTime_ <<
",\n";
1564 out <<
"\"COL_TYPES\" : {\n";
1565 for(
int c=0;c<(int)getNumberOfColumns();++c)
1567 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1568 out <<
"\"" << columnsInfo_[c].getDataType() <<
"\"";
1569 if(c+1 < (
int)getNumberOfColumns())
1575 out <<
"\"DATA_SET\" : [\n";
1577 for(
int r=0;r<(int)getNumberOfRows();++r)
1580 for(
int c=0;c<(int)getNumberOfColumns();++c)
1582 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1584 out <<
"\"" << getEscapedValueAsString(r,c,
false) <<
"\"";
1586 if(c+1 < (
int)getNumberOfColumns())
1591 if(r+1 < (
int)getNumberOfRows())
1603 std::string restoreJSONStringEntities(
const std::string &str)
1605 unsigned int sz = str.size();
1608 std::stringstream retStr;
1616 retStr <<
'\n'; ++i;
break;
1618 retStr <<
'"'; ++i;
break;
1620 retStr <<
'\t'; ++i;
break;
1622 retStr <<
'\r'; ++i;
break;
1624 retStr <<
'\\'; ++i;
break;
1632 retStr << str[sz-1];
1634 return retStr.str();
1646 int ConfigurationView::fillFromJSON(
const std::string &json)
1648 std::vector<std::string> keys;
1649 keys.push_back (
"NAME");
1650 keys.push_back (
"COMMENT");
1651 keys.push_back (
"AUTHOR");
1652 keys.push_back (
"CREATION_TIME");
1654 keys.push_back (
"DATA_SET");
1657 CV_JSON_FILL_COMMENT,
1658 CV_JSON_FILL_AUTHOR,
1659 CV_JSON_FILL_CREATION_TIME,
1661 CV_JSON_FILL_DATA_SET
1666 sourceColumnMismatchCount_ = 0;
1667 sourceColumnMissingCount_ = 0;
1668 sourceColumnNames_.clear();
1669 unsigned int colFoundCount = 0;
1671 unsigned int row = -1;
1672 unsigned int colSpeedup = 0;
1673 unsigned int startString, startNumber, endNumber = -1;
1674 unsigned int bracketCount = 0;
1675 unsigned int sqBracketCount = 0;
1679 bool isDataArray = 0;
1680 bool keyIsMatch, keyIsComment;
1681 unsigned int keyIsMatchIndex, keyIsMatchStorageIndex, keyIsMatchCommentIndex;
1682 const std::string COMMENT_ALT_KEY =
"COMMENT";
1684 std::string extractedString =
"", currKey =
"", currVal =
"";
1685 unsigned int currDepth;
1687 std::vector<std::string> jsonPath;
1688 std::vector<char> jsonPathType;
1689 char lastPopType =
'_';
1691 unsigned int matchedKey = -1;
1692 unsigned int lastCol = -1;
1696 for(;i<json.size();++i)
1701 if(i-1 < json.size() &&
1702 json[i-1] ==
'\\')
break;
1704 inQuotes = !inQuotes;
1709 extractedString = restoreJSONStringEntities(
1710 json.substr(startString+1,i-startString-1));
1718 if(jsonPathType[jsonPathType.size()-1] !=
'{'
1721 __COUT__ <<
"Invalid ':' position" << std::endl;
1726 jsonPathType.push_back(
'K');
1727 jsonPath.push_back(extractedString);
1745 if(lastPopType ==
'{')
1748 if(jsonPathType[jsonPathType.size()-1] ==
'K')
1751 jsonPath.pop_back();
1752 jsonPathType.pop_back();
1758 currVal = extractedString;
1761 if(endNumber == (
unsigned int)-1 ||
1762 endNumber <= startNumber)
1765 if(endNumber <= startNumber)
1768 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
1771 currDepth = bracketCount;
1773 if(jsonPathType[jsonPathType.size()-1] ==
'K')
1775 currKey = jsonPath[jsonPathType.size()-1];
1780 jsonPath.pop_back();
1781 jsonPathType.pop_back();
1783 else if(jsonPathType[jsonPathType.size()-1] ==
'[')
1786 for(
unsigned int k=jsonPathType.size()-2; k<jsonPathType.size(); --k)
1787 if(jsonPathType[k] ==
'K')
1789 currKey = jsonPath[k];
1794 __COUT__ <<
"Invalid array position" << std::endl;
1803 __COUT__ <<
"Invalid ',' position" << std::endl;
1813 jsonPathType.push_back(
'{');
1814 jsonPath.push_back(
"{");
1826 if(lastPopType !=
'{' &&
1827 jsonPathType[jsonPathType.size()-1] ==
'K')
1829 currDepth = bracketCount;
1830 currKey = jsonPath[jsonPathType.size()-1];
1832 currVal = extractedString;
1835 if(endNumber == (
unsigned int)-1 ||
1836 endNumber <= startNumber)
1839 if(endNumber <= startNumber)
1842 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
1846 jsonPath.pop_back();
1847 jsonPathType.pop_back();
1850 if(jsonPathType[jsonPathType.size()-1] !=
'{')
1852 __COUT__ <<
"Invalid '}' position" << std::endl;
1856 jsonPath.pop_back();
1857 jsonPathType.pop_back();
1862 jsonPathType.push_back(
'[');
1863 jsonPath.push_back(
"[");
1871 if(jsonPathType[jsonPathType.size()-1] !=
'[')
1873 __COUT__ <<
"Invalid ']' position" << std::endl;
1877 currDepth = bracketCount;
1881 currVal = extractedString;
1884 if(endNumber == (
unsigned int)-1 ||
1885 endNumber <= startNumber)
1888 if(endNumber <= startNumber)
1891 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
1896 for(
unsigned int k=jsonPathType.size()-2; k<jsonPathType.size(); --k)
1897 if(jsonPathType[k] ==
'K')
1899 currKey = jsonPath[k];
1904 __COUT__ <<
"Invalid array position" << std::endl;
1909 if(jsonPathType[jsonPathType.size()-1] !=
'[')
1911 __COUT__ <<
"Invalid ']' position" << std::endl;
1915 jsonPath.pop_back();
1916 jsonPathType.pop_back();
1924 if(startNumber != (
unsigned int)-1 &&
1925 endNumber == (
unsigned int)-1)
1934 std::cout << i <<
":\t" << json[i] <<
" - ";
1936 std::cout <<
"ExtKey=";
1937 for(
unsigned int k=0;k<jsonPath.size();++k)
1938 std::cout << jsonPath[k] <<
"/";
1940 std::cout << lastPopType <<
" ";
1941 std::cout << bracketCount <<
" ";
1942 std::cout << sqBracketCount <<
" ";
1943 std::cout << inQuotes <<
" ";
1944 std::cout << newValue <<
"-";
1945 std::cout << currKey <<
"-{" << currDepth <<
"}:" ;
1946 std::cout << currVal <<
" ";
1947 std::cout << startNumber <<
"-";
1948 std::cout << endNumber <<
" ";
1980 for(
unsigned int k=0;k<keys.size();++k)
1981 if((currDepth == 1 && keys[k] == currKey) ||
1982 (currDepth > 1 && keys[k] == jsonPath[1]))
1985 if(matchedKey != (
unsigned int)-1)
1992 case CV_JSON_FILL_NAME:
1993 if(currDepth == 1) setTableName(currVal);
1995 case CV_JSON_FILL_COMMENT:
1996 if(currDepth == 1) setComment(currVal);
1998 case CV_JSON_FILL_AUTHOR:
1999 if(currDepth == 1) setAuthor(currVal);
2001 case CV_JSON_FILL_CREATION_TIME:
2002 if(currDepth == 1) setCreationTime(strtol(currVal.c_str(),0,10));
2007 case CV_JSON_FILL_DATA_SET:
2016 unsigned int col, ccnt = 0;
2017 unsigned int noc = getNumberOfColumns();
2018 for(;ccnt<noc;++ccnt)
2024 if(fillWithLooseColumnMatching_)
2036 if(getNumberOfRows() == 1)
2037 sourceColumnNames_.emplace(currKey);
2041 if(row >= getNumberOfRows())
2043 __SS__ <<
"Invalid row" << std::endl;
2044 std::cout << ss.str();
2045 throw std::runtime_error(ss.str());
2049 theDataView_[row][col] = currVal;
2054 col = (ccnt + colSpeedup) % noc;
2060 keyIsComment =
true;
2061 for(keyIsMatchIndex=0, keyIsMatchStorageIndex=0, keyIsMatchCommentIndex=0;
2062 keyIsMatchIndex<currKey.size();++keyIsMatchIndex)
2064 if(columnsInfo_[col].getStorageName()[keyIsMatchStorageIndex] ==
'_')
2065 ++keyIsMatchStorageIndex;
2066 if(currKey[keyIsMatchIndex] ==
'_')
2070 if(keyIsMatchStorageIndex >= columnsInfo_[col].getStorageName().size() ||
2071 currKey[keyIsMatchIndex] !=
2072 columnsInfo_[col].getStorageName()[keyIsMatchStorageIndex])
2081 if(keyIsComment && keyIsMatchCommentIndex < COMMENT_ALT_KEY.size())
2083 if(currKey[keyIsMatchIndex] != COMMENT_ALT_KEY[keyIsMatchCommentIndex])
2086 keyIsComment =
false;
2090 ++keyIsMatchStorageIndex;
2093 if(keyIsMatch || keyIsComment)
2098 if(getNumberOfRows())
2099 sourceColumnMissingCount_ += getNumberOfColumns() - colFoundCount;
2107 if(getNumberOfRows() == 1)
2108 sourceColumnNames_.emplace(currKey);
2112 if(row >= getNumberOfRows())
2114 __SS__ <<
"Invalid row" << std::endl;
2115 __COUT__ <<
"\n" << ss.str();
2116 throw std::runtime_error(ss.str());
2120 theDataView_[row][col] = currVal;
2126 colSpeedup = (colSpeedup + 1) % noc;
2128 if(ccnt >= getNumberOfColumns())
2130 __SS__ <<
"\n\nInvalid column in JSON source data: " <<
2131 currKey <<
" not found in column names of table named " <<
2132 getTableName() <<
"." <<
2134 __COUT__ <<
"\n" << ss.str();
2137 ++sourceColumnMismatchCount_;
2138 if(getNumberOfRows() == 1)
2139 sourceColumnNames_.emplace(currKey);
2172 bool ConfigurationView::isURIEncodedCommentTheSame(
const std::string &comment)
const
2174 std::string compareStr = decodeURIComponent(comment);
2175 return comment_ == compareStr;
2230 int ConfigurationView::fillFromCSV(
const std::string &data,
const int &dataOffset,
2231 const std::string &author)
2232 throw(std::runtime_error)
2238 int j = data.find(
',',i);
2239 int k = data.find(
';',i);
2241 bool rowWasModified;
2242 unsigned int countRowsModified = 0;
2243 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
2244 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
2247 while(k != (
int)(std::string::npos))
2249 rowWasModified =
false;
2250 if(r >= (
int)getNumberOfRows())
2254 rowWasModified =
true;
2257 while(j < k && j != (
int)(std::string::npos))
2262 if(c >= (
int)getNumberOfColumns()-2)
2265 j = data.find(
',',i);
2270 if(setURIEncodedValue(data.substr(i,j-i),r,c))
2271 rowWasModified =
true;
2274 j = data.find(
',',i);
2279 if(author !=
"" && rowWasModified)
2281 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << std::endl;
2282 setValue(author,r,authorCol);
2283 setValue(time(0),r,timestampCol);
2286 if(rowWasModified) ++countRowsModified;
2293 j = data.find(
',',i);
2294 k = data.find(
';',i);
2298 while(r < (
int)getNumberOfRows())
2301 __COUT__ <<
"Row deleted: " << (int)r << std::endl;
2302 ++countRowsModified;
2305 __COUT_INFO__ <<
"countRowsModified=" <<
2306 countRowsModified << std::endl;
2308 if(!countRowsModified)
2310 __SS__ <<
"No rows were modified! No reason to fill a view with same content." << std::endl;
2311 __COUT__ <<
"\n" << ss.str();
2318 sourceColumnNames_.clear();
2319 for(
unsigned int i=0;i<getNumberOfColumns();++i)
2320 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
2340 bool ConfigurationView::setURIEncodedValue(
const std::string &value,
const unsigned int &r,
2341 const unsigned int &c,
const std::string &author)
2343 if(!(c < columnsInfo_.size() && r < getNumberOfRows()))
2345 __SS__ <<
"Invalid row (" << (int)r <<
") col (" << (
int)c << ") requested!" <<
2346 "Number of Rows = " << getNumberOfRows() <<
2347 "Number of Columns = " << columnsInfo_.size() << std::endl;
2349 throw std::runtime_error(ss.str());
2352 std::
string valueStr = decodeURIComponent(value);
2353 std::
string originalValueStr = getValueAsString(r,c,false);
2359 if(columnsInfo_[c].getDataType() ==
ViewColumnInfo::DATATYPE_NUMBER)
2362 std::string convertedString = convertEnvVariables(valueStr);
2363 if(!isNumber(convertedString))
2365 __SS__ <<
"\tIn configuration " << tableName_
2366 <<
" at column=" << columnsInfo_[c].getName()
2367 <<
" the value set (" << convertedString <<
")"
2368 <<
" is not a number! Please fix it or change the column type..." << std::endl;
2369 throw std::runtime_error(ss.str());
2371 theDataView_[r][c] = valueStr;
2373 else if(columnsInfo_[c].getDataType() == ViewColumnInfo::DATATYPE_TIME)
2385 setValue(time_t(strtol(valueStr.c_str(),0,10)),
2389 theDataView_[r][c] = valueStr;
2391 bool rowWasModified = (originalValueStr != getValueAsString(r,c,
false));
2394 if(author !=
"" && rowWasModified)
2396 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << std::endl;
2397 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
2398 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
2399 setValue(author,r,authorCol);
2400 setValue(time(0),r,timestampCol);
2403 return rowWasModified;
2409 std::string ConfigurationView::decodeURIComponent(
const std::string &data)
2411 std::string decodeURIString(data.size(),0);
2413 for(
unsigned int i=0;i<data.size();++i,++j)
2419 decodeURIString[j] += (data[i+1]-55)*16;
2421 decodeURIString[j] += (data[i+1]-48)*16;
2425 decodeURIString[j] += (data[i+2]-55);
2427 decodeURIString[j] += (data[i+2]-48);
2432 decodeURIString[j] = data[i];
2434 decodeURIString.resize(j);
2435 return decodeURIString;
2439 void ConfigurationView::resizeDataView(
unsigned int nRows,
unsigned int nCols)
2442 theDataView_.resize(nRows, std::vector<std::string>(nCols));
2452 int ConfigurationView::addRow(
const std::string &author,
2453 bool incrementUniqueData,
2454 std::string baseNameAutoUID)
2456 int row = getNumberOfRows();
2457 theDataView_.resize(getNumberOfRows()+1,std::vector<std::string>(getNumberOfColumns()));
2459 std::vector<std::string> defaultRowValues =
2460 getDefaultRowValues();
2462 char indexString[1000];
2463 std::string tmpString, baseString;
2466 unsigned int maxUniqueData;
2467 std::string numString;
2471 for(
unsigned int col=0;col<getNumberOfColumns();++col)
2478 if(incrementUniqueData &&
2479 (col == getColUID() || (row && columnsInfo_[col].getType() ==
2480 ViewColumnInfo::TYPE_UNIQUE_DATA)))
2493 for(
unsigned int r=0;r<getNumberOfRows()-1;++r)
2498 tmpString = theDataView_[r][col];
2502 for(index = tmpString.length()-1;index < tmpString.length(); --index)
2505 if(!(tmpString[index] >=
'0' && tmpString[index] <=
'9'))
break;
2511 if(tmpString.length() &&
2515 numString = tmpString.substr(index+1);
2516 tmpString = tmpString.substr(0,index+1);
2523 sscanf(numString.c_str(),
"%u",&index);
2525 if(index > maxUniqueData)
2527 maxUniqueData = index;
2528 baseString = tmpString;
2535 sprintf(indexString,
"%u",maxUniqueData);
2539 if(col == getColUID())
2542 if(baseNameAutoUID !=
"")
2543 theDataView_[row][col] = baseNameAutoUID + indexString;
2545 theDataView_[row][col] = baseString + indexString;
2548 theDataView_[row][col] = baseString + indexString;
2550 __COUT__ <<
"New unique data entry is '" << theDataView_[row][col] <<
"'" << __E__;
2555 theDataView_[row][col] = defaultRowValues[col];
2560 __COUT__ <<
"Row=" << row <<
" was created!" << std::endl;
2561 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
2562 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
2563 setValue(author,row,authorCol);
2564 setValue(time(0),row,timestampCol);
2594 void ConfigurationView::deleteRow(
int r)
2596 if(r >= (
int)getNumberOfRows())
2599 __SS__ <<
"Row " << (int)r <<
" is out of bounds (Row Count = " <<
2600 getNumberOfRows() <<
") and can not be deleted." <<
2602 throw std::runtime_error(ss.str());
2605 theDataView_.erase(theDataView_.begin()+r);
2622 const bool ConfigurationView::getChildLink(
const unsigned int& c,
bool& isGroup,
2623 std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>& linkPair)
const
2626 if(!(c < columnsInfo_.size()))
2628 __SS__ <<
"Invalid col (" << (int)c <<
") requested!" << std::endl;
2629 throw std::runtime_error(ss.str());
2636 if((isGroup = columnsInfo_[c].isChildLinkGroupID()) ||
2637 columnsInfo_[c].isChildLinkUID())
2641 linkPair.second = c;
2642 std::string index = columnsInfo_[c].getChildLinkIndex();
2647 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
2650 if(col == c)
continue;
2651 else if(columnsInfo_[col].isChildLink() &&
2652 index == columnsInfo_[col].getChildLinkIndex())
2656 linkPair.first = col;
2662 __SS__ <<
"\tIn view: " << tableName_ <<
2663 ", Can't find complete child link for column name " << columnsInfo_[c].getName() << std::endl;
2664 throw std::runtime_error(ss.str());
2667 if(!columnsInfo_[c].isChildLink())
2672 std::string index = columnsInfo_[c].getChildLinkIndex();
2677 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
2680 if(col == c)
continue;
2692 if(((columnsInfo_[col].isChildLinkUID() && !(isGroup =
false)) ||
2693 (columnsInfo_[col].isChildLinkGroupID() && (isGroup =
true)))
2694 && index == columnsInfo_[col].getChildLinkIndex())
2698 linkPair.second = col;
2704 __SS__ <<
"\tIn view: " << tableName_ <<
2705 ", Can't find complete child link id for column name " << columnsInfo_[c].getName() << std::endl;
2706 throw std::runtime_error(ss.str());
2712 bool ConfigurationView::isNumber(
const std::string& s)
const
2715 if(s.find(
"0x") == 0)
2718 for(
unsigned int i=2;i<s.size();++i)
2720 if(!((s[i] >=
'0' && s[i] <=
'9') ||
2721 (s[i] >=
'A' && s[i] <=
'F') ||
2722 (s[i] >=
'a' && s[i] <=
'f')
2731 else if(s[0] ==
'b')
2735 for(
unsigned int i=1;i<s.size();++i)
2737 if(!((s[i] >=
'0' && s[i] <=
'1')
2748 for(
unsigned int i=0;i<s.size();++i)
2749 if(!((s[i] >=
'0' && s[i] <=
'9') ||
2769 std::string ots_demangle(
const char* name) {
2774 std::unique_ptr<char, void(*)(void*)> res {
2775 abi::__cxa_demangle(name, NULL, NULL, &status),
2779 return (status==0) ? res.get() : name ;
2785 std::string ots_demangle(
const char* name) {