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] ==
'-' || theDataView_[row][colUID_][i] <=
'_')
242 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' " <<
243 " was identified. UIDs must contain only letters, numbers," <<
244 "dashes, and underscores." << std::endl;
245 throw std::runtime_error(ss.str());
248 uidSet.insert(theDataView_[row][colUID_]);
250 if(uidSet.size() != getNumberOfRows())
252 __SS__ <<
"Entries in UID are not unique!" <<
253 "There are " << getNumberOfRows() <<
254 " rows and the unique UID count is " << uidSet.size() << std::endl;
255 __COUT_ERR__ <<
"\n" << ss.str();
256 throw std::runtime_error(ss.str());
260 colPos = (
unsigned int)-1;
261 while((colPos = findColByType(ViewColumnInfo::TYPE_UNIQUE_DATA,colPos+1)) != INVALID)
263 std::set<std::string > uDataSet;
264 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
266 if(uDataSet.find(theDataView_[row][colPos]) != uDataSet.end())
268 __SS__ <<
"Entries in Unique Data column " <<
269 columnsInfo_[colPos].getName() <<
270 (
" are not unique. Specifically at row=" +
271 std::to_string(row) +
" value=" + theDataView_[row][colPos]) <<
273 __COUT_ERR__ <<
"\n" << ss.str();
274 throw std::runtime_error(ss.str());
276 uDataSet.insert(theDataView_[row][colPos]);
278 if(uDataSet.size() != getNumberOfRows())
280 __SS__ <<
"Entries in Unique Data column " <<
281 columnsInfo_[colPos].getName() <<
" are not unique!" <<
282 "There are " << getNumberOfRows() <<
283 " rows and the unique data count is " << uDataSet.size() << std::endl;
284 __COUT_ERR__ <<
"\n" << ss.str();
285 throw std::runtime_error(ss.str());
289 auto rowDefaults = getDefaultRowValues();
296 std::set<std::string> groupIdIndexes, childLinkIndexes, childLinkIdLabels;
297 unsigned int groupIdIndexesCount = 0, childLinkIndexesCount = 0, childLinkIdLabelsCount = 0;
298 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
300 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
302 const std::vector<std::string>& theDataChoices =
303 columnsInfo_[col].getDataChoices();
306 if(theDataChoices.size() && theDataChoices[0] ==
311 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
315 if(theDataView_[row][col] == rowDefaults[col])
318 for(
const auto &choice:theDataChoices)
320 if(theDataView_[row][col] == choice)
328 __SS__ <<
"Configuration Error:\t'" << theDataView_[row][col] <<
"' in column " <<
329 columnsInfo_[col].getName() <<
" is not a valid Fixed Choice option. " <<
330 "Possible values are as follows: ";
332 for(
unsigned int i = 0; i < columnsInfo_[col].getDataChoices().size(); ++i)
335 ss << columnsInfo_[col].getDataChoices()[i];
337 ss <<
"." << std::endl;
338 __COUT_ERR__ <<
"\n" << ss.str();
339 throw std::runtime_error(ss.str());
343 if(columnsInfo_[col].isChildLink())
347 const std::vector<std::string>& theDataChoices =
348 columnsInfo_[col].getDataChoices();
351 if(!theDataChoices.size() ||
352 theDataChoices[0] ==
"arbitraryBool=1")
356 bool skipOne = (theDataChoices.size() &&
357 theDataChoices[0] ==
"arbitraryBool=0");
361 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
366 for(
const auto &choice:theDataChoices)
368 if(skipOne && !hasSkipped) {hasSkipped =
true;
continue;}
370 if(theDataView_[row][col] == choice)
378 __SS__ <<
"Configuration Error:\t'" << theDataView_[row][col] <<
"' in column " <<
379 columnsInfo_[col].getName() <<
" is not a valid Fixed Choice option. " <<
380 "Possible values are as follows: ";
382 for(
unsigned int i = skipOne?1:0; i < columnsInfo_[col].getDataChoices().size(); ++i)
384 if(i == 1 + (skipOne?1:0)) ss <<
", ";
385 ss << columnsInfo_[col].getDataChoices()[i];
387 ss <<
"." << std::endl;
388 __COUT_ERR__ <<
"\n" << ss.str();
389 throw std::runtime_error(ss.str());
393 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_ON_OFF)
394 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
396 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" || theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
397 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_ON;
398 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"off" || theDataView_[row][col] ==
"Off" || theDataView_[row][col] ==
"OFF")
399 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_OFF;
402 __SS__ <<
"Configuration Error:\t" << theDataView_[row][col] <<
" in column " <<
403 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;
404 __COUT_ERR__ <<
"\n" << ss.str();
405 throw std::runtime_error(ss.str());
408 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_TRUE_FALSE)
409 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
411 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" || theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
412 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_TRUE;
413 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"false" || theDataView_[row][col] ==
"False" || theDataView_[row][col] ==
"FALSE")
414 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_FALSE;
417 __SS__ <<
"Configuration Error:\t" << theDataView_[row][col] <<
" in column " <<
418 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;
419 __COUT_ERR__ <<
"\n" << ss.str();
420 throw std::runtime_error(ss.str());
423 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_YES_NO)
424 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
426 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" || theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
427 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_YES;
428 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"no" || theDataView_[row][col] ==
"No" || theDataView_[row][col] ==
"NO")
429 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_NO;
432 __SS__ <<
"Configuration Error:\t" << theDataView_[row][col] <<
" in column " <<
433 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;
434 __COUT_ERR__ <<
"\n" << ss.str();
435 throw std::runtime_error(ss.str());
438 else if(columnsInfo_[col].isGroupID())
440 colLinkGroupIDs_[columnsInfo_[col].getChildLinkIndex()] = col;
442 groupIdIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
443 ++groupIdIndexesCount;
445 else if(columnsInfo_[col].isChildLink())
448 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
449 if(theDataView_[row][col] ==
"NoLink" ||
450 theDataView_[row][col] ==
"No_Link" ||
451 theDataView_[row][col] ==
"NOLINK" ||
452 theDataView_[row][col] ==
"NO_LINK" ||
453 theDataView_[row][col] ==
"Nolink" ||
454 theDataView_[row][col] ==
"nolink" ||
455 theDataView_[row][col] ==
"noLink")
456 theDataView_[row][col] = ViewColumnInfo::DATATYPE_LINK_DEFAULT;
459 childLinkIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
460 ++childLinkIndexesCount;
463 if(columnsInfo_[col].getDataType() != ViewColumnInfo::DATATYPE_STRING)
465 __SS__ <<
"Configuration Error:\t" <<
"Column " << col <<
466 " with name " << columnsInfo_[col].getName() <<
467 " is a Child Link column and has an illegal data type of '" <<
468 columnsInfo_[col].getDataType() <<
469 "'. The data type for Child Link columns must be " <<
470 ViewColumnInfo::DATATYPE_STRING << std::endl;
471 __COUT_ERR__ <<
"\n" << ss.str();
472 throw std::runtime_error(ss.str());
476 else if(columnsInfo_[col].isChildLinkUID() ||
477 columnsInfo_[col].isChildLinkGroupID())
480 childLinkIdLabels.emplace(columnsInfo_[col].getChildLinkIndex());
481 ++childLinkIdLabelsCount;
484 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
485 if(theDataView_[row][col] ==
"")
486 theDataView_[row][col] = rowDefaults[col];
492 if(groupIdIndexes.size() != groupIdIndexesCount)
494 __SS__ << (
"GroupId Labels are not unique!") <<
495 "There are " << groupIdIndexesCount <<
496 " GroupId Labels and the unique count is " << groupIdIndexes.size() << std::endl;
497 __COUT_ERR__ <<
"\n" << ss.str();
498 throw std::runtime_error(ss.str());
500 if(childLinkIndexes.size() != childLinkIndexesCount)
502 __SS__ << (
"Child Link Labels are not unique!") <<
503 "There are " << childLinkIndexesCount <<
504 " Child Link Labels and the unique count is " << childLinkIndexes.size() << std::endl;
505 __COUT_ERR__ <<
"\n" << ss.str();
506 throw std::runtime_error(ss.str());
508 if(childLinkIdLabels.size() != childLinkIdLabelsCount)
510 __SS__ << (
"Child Link ID Labels are not unique!") <<
511 "There are " << childLinkIdLabelsCount <<
512 " Child Link ID Labels and the unique count is " << childLinkIdLabels.size() << std::endl;
513 __COUT_ERR__ <<
"\n" << ss.str();
514 throw std::runtime_error(ss.str());
520 __COUT__ <<
"Error occured in ConfigurationView::init() for version=" << version_ << std::endl;
529 void ConfigurationView::getValue(std::string& value,
unsigned int row,
unsigned int col,
bool convertEnvironmentVariables)
const
533 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
535 __SS__ <<
"Invalid row col requested" << std::endl;
536 __COUT_ERR__ <<
"\n" << ss.str();
537 throw std::runtime_error(ss.str());
540 value = validateValueForColumn(theDataView_[row][col],col,convertEnvironmentVariables);
583 std::string ConfigurationView::validateValueForColumn(
const std::string& value,
unsigned int col,
bool convertEnvironmentVariables)
const
586 if(col >= columnsInfo_.size())
588 __SS__ <<
"Invalid col requested" << std::endl;
589 __COUT_ERR__ <<
"\n" << ss.str();
590 throw std::runtime_error(ss.str());
593 std::string retValue;
595 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING)
596 retValue = convertEnvironmentVariables?convertEnvVariables(value):value;
597 else if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_TIME)
601 strtol((convertEnvironmentVariables?convertEnvVariables(value):value).c_str(),
604 ::localtime_r(×tamp, &tmstruct);
605 ::strftime(&retValue[0], 30,
"%c %Z", &tmstruct);
606 retValue.resize(strlen(retValue.c_str()));
610 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
611 <<
" in configuration " << tableName_
612 <<
" at column=" << columnsInfo_[col].getName()
613 <<
" for getValue with type '" << ots_demangle(
typeid(retValue).name())
615 __COUT_ERR__ <<
"\n" << ss.str();
616 throw std::runtime_error(ss.str());
627 std::string ConfigurationView::getValueAsString(
unsigned int row,
unsigned int col,
628 bool convertEnvironmentVariables)
const
630 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
632 __SS__ << (
"Invalid row col requested") << std::endl;
633 __COUT_ERR__ << ss.str();
634 throw std::runtime_error(ss.str());
639 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_ON_OFF)
641 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" || theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
642 return ViewColumnInfo::TYPE_VALUE_ON;
644 return ViewColumnInfo::TYPE_VALUE_OFF;
646 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_TRUE_FALSE)
648 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" || theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
649 return ViewColumnInfo::TYPE_VALUE_TRUE;
651 return ViewColumnInfo::TYPE_VALUE_FALSE;
653 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_YES_NO)
655 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" || theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
656 return ViewColumnInfo::TYPE_VALUE_YES;
658 return ViewColumnInfo::TYPE_VALUE_NO;
662 return convertEnvironmentVariables?convertEnvVariables(theDataView_[row][col]):
663 theDataView_[row][col];
673 std::string ConfigurationView::getEscapedValueAsString(
unsigned int row,
unsigned int col,
674 bool convertEnvironmentVariables)
const
676 std::string val = getValueAsString(row,col,convertEnvironmentVariables);
677 std::string retVal =
"";
678 retVal.reserve(val.size());
679 for(
unsigned int i=0;i<val.size();++i)
683 else if(val[i] ==
'\t')
685 else if(val[i] ==
'\r')
700 std::string ConfigurationView::convertEnvVariables(
const std::string& data)
const
702 std::string converted = data;
703 if(data.find(
"${") != std::string::npos)
705 unsigned int begin = data.find(
"${");
706 unsigned int end = data.find(
"}");
707 std::string envVariable = data.substr(begin+2, end-begin-2);
709 if(getenv(envVariable.c_str()) !=
nullptr)
711 return convertEnvVariables(converted.replace(begin,end-begin+1,getenv(envVariable.c_str())));
715 __SS__ << (
"In configuration " + tableName_ +
" the environmental variable: " + envVariable +
716 " is not set! Please make sure you set it before continuing!") << std::endl;
717 __COUT_ERR__ << ss.str();
718 throw std::runtime_error(ss.str());
727 void ConfigurationView::setValue(
const std::string &value,
unsigned int row,
unsigned int col)
729 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
731 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << std::endl;
732 throw std::runtime_error(ss.str());
735 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING)
736 theDataView_[row][col] = value;
740 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
741 <<
" in configuration " << tableName_
742 <<
" at column=" << columnsInfo_[col].getName()
743 <<
" for setValue with type '" << ots_demangle(
typeid(value).name())
745 throw std::runtime_error(ss.str());
748 void ConfigurationView::setValue(
const char *value,
unsigned int row,
unsigned int col)
749 { setValue(std::string(value),row,col); }
754 void ConfigurationView::setValueAsString(
const std::string &value,
unsigned int row,
unsigned int col)
756 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
758 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << std::endl;
759 throw std::runtime_error(ss.str());
762 theDataView_[row][col] = value;
768 const unsigned int ConfigurationView::getOrInitColUID(
void)
770 if(colUID_ != INVALID)
return colUID_;
773 colUID_ = findColByType(ViewColumnInfo::TYPE_UID);
774 if(colUID_ == INVALID)
776 __COUT__ <<
"Column Types: " << std::endl;
777 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
778 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
779 __SS__ <<
"\tMissing UID Column in table named '" << tableName_ <<
"'" << std::endl;
780 __COUT_ERR__ <<
"\n" << ss.str() << std::endl;
781 throw std::runtime_error(ss.str());
789 const unsigned int ConfigurationView::getColUID(
void)
const
791 if(colUID_ != INVALID)
return colUID_;
793 __COUT__ <<
"Column Types: " << std::endl;
794 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
795 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
797 __SS__ << (
"Missing UID Column in config named " + tableName_ +
798 ". (Possibly ConfigurationView was just not initialized?" +
799 "This is the const call so can not alter class members)") << std::endl;
800 __COUT_ERR__ <<
"\n" << ss.str() << std::endl;
801 throw std::runtime_error(ss.str());
807 const unsigned int ConfigurationView::getOrInitColStatus(
void)
809 if(colStatus_ != INVALID)
return colStatus_;
812 colStatus_ = findCol(ViewColumnInfo::COL_NAME_STATUS);
813 if(colStatus_ == INVALID)
815 __SS__ <<
"\tMissing Status Column in table named '" << tableName_ <<
"'" << std::endl;
816 ss <<
"Column Types: " << std::endl;
817 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
818 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
821 throw std::runtime_error(ss.str());
829 const unsigned int ConfigurationView::getColStatus(
void)
const
831 if(colStatus_ != INVALID)
return colStatus_;
833 __COUT__ <<
"Column Types: " << std::endl;
834 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
835 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
837 __SS__ << (
"Missing Status Column in config named " + tableName_ +
838 ". (Possibly ConfigurationView was just not initialized?" +
839 "This is the const call so can not alter class members)") << std::endl;
840 __COUT_ERR__ <<
"\n" << ss.str() << std::endl;
841 throw std::runtime_error(ss.str());
847 void ConfigurationView::addRowToGroup(
const unsigned int &row,
848 const unsigned int &col,
849 const std::string &groupID)
852 if(isEntryInGroupCol(row,col,groupID))
854 __SS__ <<
"GroupID (" << groupID <<
855 ") added to row (" << row
856 <<
" is already present!" << std::endl;
857 throw std::runtime_error(ss.str());
865 if(getDataView()[row][col] ==
"" ||
866 getDataView()[row][col] == getDefaultRowValues()[col])
872 groupID +
" | " + getDataView()[row][col],
883 bool ConfigurationView::removeRowFromGroup(
const unsigned int &row,
884 const unsigned int &col,
885 const std::string &groupNeedle,
886 bool deleteRowIfNoGroupLeft)
888 __COUT__ <<
"groupNeedle " << groupNeedle << std::endl;
889 std::set<std::string> groupIDList;
890 if(!isEntryInGroupCol(row,col,groupNeedle,&groupIDList))
892 __SS__ <<
"GroupID (" << groupNeedle <<
893 ") removed from row (" << row
894 <<
") was already removed!" << std::endl;
895 throw std::runtime_error(ss.str());
902 std::string newValue =
"";
903 unsigned int cnt = 0;
904 for(
const auto & groupID : groupIDList)
907 if(groupID == groupNeedle)
continue;
909 if(cnt) newValue +=
" | ";
913 bool wasDeleted =
false;
914 if(deleteRowIfNoGroupLeft && newValue ==
"")
916 __COUT__ <<
"Delete row since it no longer part of any group." << std::endl;
921 setValue(newValue,row,col);
934 bool ConfigurationView::isEntryInGroup(
const unsigned int &r,
935 const std::string &childLinkIndex,
936 const std::string &groupNeedle)
const
938 unsigned int c = getColLinkGroupID(childLinkIndex);
940 return isEntryInGroupCol(r,c,groupNeedle);
953 bool ConfigurationView::isEntryInGroupCol(
const unsigned int &r,
954 const unsigned int &c,
const std::string &groupNeedle,
955 std::set<std::string> *groupIDList)
const
964 for(;j<theDataView_[r][c].size();++j)
965 if((theDataView_[r][c][j] ==
' ' ||
966 theDataView_[r][c][j] ==
'|')
969 else if((theDataView_[r][c][j] ==
' ' ||
970 theDataView_[r][c][j] ==
'|')
973 if(groupIDList) groupIDList->emplace(theDataView_[r][c].substr(i,j-i));
977 if(groupNeedle == theDataView_[r][c].substr(i,j-i))
989 if(groupIDList) groupIDList->emplace(theDataView_[r][c].substr(i,j-i));
993 if(groupNeedle == theDataView_[r][c].substr(i,j-i))
1008 std::set<std::string> ConfigurationView::getSetOfGroupIDs(
const std::string &childLinkIndex,
1009 unsigned int r)
const
1011 unsigned int c = getColLinkGroupID(childLinkIndex);
1015 std::set<std::string> retSet;
1020 if(r != (
unsigned int)-1)
1022 if(r >= getNumberOfRows())
1024 __SS__ <<
"Invalid row requested!" << std::endl;
1025 throw std::runtime_error(ss.str());
1030 for(;j<theDataView_[r][c].size();++j)
1031 if((theDataView_[r][c][j] ==
' ' ||
1032 theDataView_[r][c][j] ==
'|')
1035 else if((theDataView_[r][c][j] ==
' ' ||
1036 theDataView_[r][c][j] ==
'|')
1043 retSet.emplace(theDataView_[r][c].substr(i,j-i));
1050 retSet.emplace(theDataView_[r][c].substr(i,j-i));
1055 for(r=0;r<getNumberOfRows();++r)
1064 for(;j<theDataView_[r][c].size();++j)
1068 if((theDataView_[r][c][j] ==
' ' ||
1069 theDataView_[r][c][j] ==
'|')
1072 else if((theDataView_[r][c][j] ==
' ' ||
1073 theDataView_[r][c][j] ==
'|')
1079 retSet.emplace(theDataView_[r][c].substr(i,j-i));
1090 retSet.emplace(theDataView_[r][c].substr(i,j-i));
1101 const unsigned int ConfigurationView::getColLinkGroupID(
const std::string &childLinkIndex)
const
1103 std::map<std::string, unsigned int>::const_iterator it = colLinkGroupIDs_.find(childLinkIndex);
1105 colLinkGroupIDs_.end())
1108 __COUT__ <<
"Existing Column Types: " << std::endl;
1109 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
1110 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
1112 __SS__ << (
"Incompatible table for this group link. Table '" +
1113 tableName_ +
"' is missing a GroupID column with data type '" +
1114 (ViewColumnInfo::TYPE_START_GROUP_ID +
"-" + childLinkIndex) +
1115 "'." ) << std::endl;
1116 __COUT_ERR__ <<
"\n" << ss.str();
1117 throw std::runtime_error(ss.str());
1121 unsigned int ConfigurationView::findRow(
unsigned int col,
const std::string& value,
unsigned int offsetRow)
const
1123 for(
unsigned int row=offsetRow; row<theDataView_.size(); ++row)
1125 if(theDataView_[row][col] == value)
1129 __SS__ <<
"\tIn view: " << tableName_
1130 <<
", Can't find value=" << value
1131 <<
" in column named " << columnsInfo_[col].getName()
1132 <<
" with type=" << columnsInfo_[col].getType()
1137 throw std::runtime_error(ss.str());
1141 unsigned int ConfigurationView::findRowInGroup(
unsigned int col,
const std::string& value,
1142 const std::string &groupId,
const std::string &childLinkIndex,
unsigned int offsetRow)
const
1144 unsigned int groupIdCol = getColLinkGroupID(childLinkIndex);
1145 for(
unsigned int row=offsetRow; row<theDataView_.size(); ++row)
1147 if(theDataView_[row][col] == value &&
1148 isEntryInGroupCol(row,groupIdCol,groupId))
1152 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find in group the value=" <<
1153 value <<
" in column named '" <<
1154 columnsInfo_[col].getName() <<
"' with type=" <<
1155 columnsInfo_[col].getType() <<
" and GroupID: '" <<
1156 groupId <<
"' in column '" << groupIdCol <<
1157 "' with GroupID child link index '" << childLinkIndex <<
"'" << std::endl;
1161 throw std::runtime_error(ss.str());
1167 unsigned int ConfigurationView::findCol(
const std::string& name)
const
1169 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
1170 if(columnsInfo_[col].getName() == name)
1173 __SS__ <<
"\tIn view: " << tableName_ <<
1174 ", Can't find column named '" << name <<
"'" << std::endl;
1175 ss <<
"Existing columns:\n";
1176 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
1177 ss <<
"\t" << columnsInfo_[col].getName() <<
"\n";
1178 throw std::runtime_error(ss.str());
1184 unsigned int ConfigurationView::findColByType(
const std::string& type,
int startingCol)
const
1186 for(
unsigned int col=startingCol; col<columnsInfo_.size(); ++col)
1187 if(columnsInfo_[col].getType() == type)
1195 const std::string& ConfigurationView::getUniqueStorageIdentifier(
void)
const
1197 return uniqueStorageIdentifier_;
1201 const std::string& ConfigurationView::getTableName(
void)
const
1213 const std::string& ConfigurationView::getComment(
void)
const
1219 const std::string& ConfigurationView::getAuthor(
void)
const
1225 const time_t& ConfigurationView::getCreationTime(
void)
const
1227 return creationTime_;
1231 const time_t& ConfigurationView::getLastAccessTime(
void)
const
1233 return lastAccessTime_;
1237 const bool& ConfigurationView::getLooseColumnMatching(
void)
const
1239 return fillWithLooseColumnMatching_;
1244 const unsigned int ConfigurationView::getDataColumnSize(
void)
const
1247 if(!getNumberOfRows())
return getNumberOfColumns();
1248 return theDataView_[0].size();
1254 const unsigned int& ConfigurationView::getSourceColumnMismatch(
void)
const
1256 return sourceColumnMismatchCount_;
1262 const unsigned int& ConfigurationView::getSourceColumnMissing(
void)
const
1264 return sourceColumnMissingCount_;
1270 const std::set<std::string>& ConfigurationView::getSourceColumnNames(
void)
const
1272 return sourceColumnNames_;
1276 std::set<std::string> ConfigurationView::getColumnNames(
void)
const
1278 std::set<std::string> retSet;
1279 for(
auto &colInfo: columnsInfo_)
1280 retSet.emplace(colInfo.getName());
1285 std::set<std::string> ConfigurationView::getColumnStorageNames(
void)
const
1287 std::set<std::string> retSet;
1288 for(
auto &colInfo: columnsInfo_)
1289 retSet.emplace(colInfo.getStorageName());
1294 std::vector<std::string> ConfigurationView::getDefaultRowValues(
void)
const
1296 std::vector<std::string> retVec;
1299 for(
unsigned int col=0;col<getNumberOfColumns();++col)
1306 if(columnsInfo_[col].isChildLink())
1308 const std::vector<std::string>& theDataChoices =
1309 columnsInfo_[col].getDataChoices();
1312 if(!theDataChoices.size() ||
1313 theDataChoices[0] ==
"arbitraryBool=1")
1314 retVec.push_back(columnsInfo_[col].getDefaultValue());
1317 bool skipOne = (theDataChoices.size() &&
1318 theDataChoices[0] ==
"arbitraryBool=0");
1323 bool foundDefault =
false;
1325 for(
const auto &choice:theDataChoices)
1326 if(skipOne && !hasSkipped) {hasSkipped =
true;
continue;}
1327 else if(choice == columnsInfo_[col].getDefaultValue())
1329 foundDefault =
true;
1334 if(!foundDefault && theDataChoices.size() > (skipOne?1:0))
1335 retVec.push_back(theDataChoices[(skipOne?1:0)]);
1337 retVec.push_back(columnsInfo_[col].getDefaultValue());
1341 retVec.push_back(columnsInfo_[col].getDefaultValue());
1348 unsigned int ConfigurationView::getNumberOfRows(
void)
const
1350 return theDataView_.size();
1354 unsigned int ConfigurationView::getNumberOfColumns(
void)
const
1356 return columnsInfo_.size();
1360 const ConfigurationView::DataView& ConfigurationView::getDataView(
void)
const
1362 return theDataView_;
1372 const std::vector<ViewColumnInfo>& ConfigurationView::getColumnsInfo (
void)
const
1374 return columnsInfo_;
1378 std::vector<ViewColumnInfo>* ConfigurationView::getColumnsInfoP(
void)
1380 return &columnsInfo_;
1383 const ViewColumnInfo& ConfigurationView::getColumnInfo(
unsigned int column)
const
1385 if(column >= columnsInfo_.size())
1387 std::stringstream errMsg;
1388 errMsg << __COUT_HDR_FL__ <<
"\nCan't find column " << column <<
1389 "\n\n\n\nThe column info is likely missing due to incomplete Configuration View filling.\n\n"
1391 throw std::runtime_error(errMsg.str().c_str());
1393 return columnsInfo_[column];
1398 void ConfigurationView::setUniqueStorageIdentifier(
const std::string &storageUID)
1400 uniqueStorageIdentifier_ = storageUID;
1404 void ConfigurationView::setTableName(
const std::string &name)
1410 void ConfigurationView::setComment(
const std::string &comment)
1416 void ConfigurationView::setURIEncodedComment(
const std::string &uriComment)
1418 comment_ = decodeURIComponent(uriComment);
1422 void ConfigurationView::setAuthor(
const std::string &author)
1428 void ConfigurationView::setCreationTime(time_t t)
1434 void ConfigurationView::setLastAccessTime(time_t t)
1436 lastAccessTime_ = t;
1440 void ConfigurationView::setLooseColumnMatching(
bool setValue)
1442 fillWithLooseColumnMatching_ = setValue;
1446 void ConfigurationView::reset (
void)
1451 columnsInfo_.clear();
1452 theDataView_.clear();
1456 void ConfigurationView::print (std::ostream &out)
const
1458 out <<
"==============================================================================" << std::endl;
1459 out <<
"Print: " << tableName_ <<
" Version: " << version_ <<
" Comment: " << comment_ <<
1460 " Author: " << author_ <<
" Creation Time: " << ctime(&creationTime_) << std::endl;
1461 out <<
"\t\tNumber of Cols " << getNumberOfColumns() << std::endl;
1462 out <<
"\t\tNumber of Rows " << getNumberOfRows() << std::endl;
1464 out <<
"Columns:\t";
1465 for(
int i=0;i<(int)columnsInfo_.size();++i)
1466 out << i <<
":" << columnsInfo_[i].getName() <<
":" << columnsInfo_[i].getStorageName() <<
":" << columnsInfo_[i].getDataType() <<
"\t ";
1469 out <<
"Rows:" << std::endl;
1472 for(
int r=0;r<(int)getNumberOfRows();++r)
1474 out << (int)r <<
":\t";
1475 for(
int c=0;c<(int)getNumberOfColumns();++c)
1477 out << (int)c <<
":";
1480 if(columnsInfo_[c].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
1482 int choiceIndex = -1;
1483 std::vector<std::string> choices = columnsInfo_[c].getDataChoices();
1484 val = convertEnvVariables(theDataView_[r][c]);
1486 if(val == columnsInfo_[c].getDefaultValue())
1490 for(
int i=0;i<(int)choices.size();++i)
1491 if(val == choices[i])
1495 out <<
"ChoiceIndex=" << choiceIndex <<
":";
1499 out << theDataView_[r][c];
1520 void ConfigurationView::printJSON (std::ostream &out)
const
1523 out <<
"\"NAME\" : \"" << tableName_ <<
"\",\n";
1527 out <<
"\"COMMENT\" : ";
1533 for(
unsigned int i=0;i<val.size();++i)
1538 else if(val[i] ==
'\t')
1540 else if(val[i] ==
'\r')
1553 out <<
"\"AUTHOR\" : \"" << author_ <<
"\",\n";
1554 out <<
"\"CREATION_TIME\" : " << creationTime_ <<
",\n";
1561 out <<
"\"COL_TYPES\" : {\n";
1562 for(
int c=0;c<(int)getNumberOfColumns();++c)
1564 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1565 out <<
"\"" << columnsInfo_[c].getDataType() <<
"\"";
1566 if(c+1 < (
int)getNumberOfColumns())
1572 out <<
"\"DATA_SET\" : [\n";
1574 for(
int r=0;r<(int)getNumberOfRows();++r)
1577 for(
int c=0;c<(int)getNumberOfColumns();++c)
1579 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1581 out <<
"\"" << getEscapedValueAsString(r,c,
false) <<
"\"";
1583 if(c+1 < (
int)getNumberOfColumns())
1588 if(r+1 < (
int)getNumberOfRows())
1600 std::string restoreJSONStringEntities(
const std::string &str)
1602 unsigned int sz = str.size();
1605 std::stringstream retStr;
1613 retStr <<
'\n'; ++i;
break;
1615 retStr <<
'"'; ++i;
break;
1617 retStr <<
'\t'; ++i;
break;
1619 retStr <<
'\r'; ++i;
break;
1621 retStr <<
'\\'; ++i;
break;
1629 retStr << str[sz-1];
1631 return retStr.str();
1643 int ConfigurationView::fillFromJSON(
const std::string &json)
1645 std::vector<std::string> keys;
1646 keys.push_back (
"NAME");
1647 keys.push_back (
"COMMENT");
1648 keys.push_back (
"AUTHOR");
1649 keys.push_back (
"CREATION_TIME");
1651 keys.push_back (
"DATA_SET");
1654 CV_JSON_FILL_COMMENT,
1655 CV_JSON_FILL_AUTHOR,
1656 CV_JSON_FILL_CREATION_TIME,
1658 CV_JSON_FILL_DATA_SET
1663 sourceColumnMismatchCount_ = 0;
1664 sourceColumnMissingCount_ = 0;
1665 sourceColumnNames_.clear();
1666 unsigned int colFoundCount = 0;
1668 unsigned int row = -1;
1669 unsigned int colSpeedup = 0;
1670 unsigned int startString, startNumber, endNumber = -1;
1671 unsigned int bracketCount = 0;
1672 unsigned int sqBracketCount = 0;
1676 bool isDataArray = 0;
1677 bool keyIsMatch, keyIsComment;
1678 unsigned int keyIsMatchIndex, keyIsMatchStorageIndex, keyIsMatchCommentIndex;
1679 const std::string COMMENT_ALT_KEY =
"COMMENT";
1681 std::string extractedString =
"", currKey =
"", currVal =
"";
1682 unsigned int currDepth;
1684 std::vector<std::string> jsonPath;
1685 std::vector<char> jsonPathType;
1686 char lastPopType =
'_';
1688 unsigned int matchedKey = -1;
1689 unsigned int lastCol = -1;
1693 for(;i<json.size();++i)
1698 if(i-1 < json.size() &&
1699 json[i-1] ==
'\\')
break;
1701 inQuotes = !inQuotes;
1706 extractedString = restoreJSONStringEntities(
1707 json.substr(startString+1,i-startString-1));
1715 if(jsonPathType[jsonPathType.size()-1] !=
'{'
1718 __COUT__ <<
"Invalid ':' position" << std::endl;
1723 jsonPathType.push_back(
'K');
1724 jsonPath.push_back(extractedString);
1742 if(lastPopType ==
'{')
1745 if(jsonPathType[jsonPathType.size()-1] ==
'K')
1748 jsonPath.pop_back();
1749 jsonPathType.pop_back();
1755 currVal = extractedString;
1758 if(endNumber == (
unsigned int)-1 ||
1759 endNumber <= startNumber)
1762 if(endNumber <= startNumber)
1765 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
1768 currDepth = bracketCount;
1770 if(jsonPathType[jsonPathType.size()-1] ==
'K')
1772 currKey = jsonPath[jsonPathType.size()-1];
1777 jsonPath.pop_back();
1778 jsonPathType.pop_back();
1780 else if(jsonPathType[jsonPathType.size()-1] ==
'[')
1783 for(
unsigned int k=jsonPathType.size()-2; k<jsonPathType.size(); --k)
1784 if(jsonPathType[k] ==
'K')
1786 currKey = jsonPath[k];
1791 __COUT__ <<
"Invalid array position" << std::endl;
1800 __COUT__ <<
"Invalid ',' position" << std::endl;
1810 jsonPathType.push_back(
'{');
1811 jsonPath.push_back(
"{");
1823 if(lastPopType !=
'{' &&
1824 jsonPathType[jsonPathType.size()-1] ==
'K')
1826 currDepth = bracketCount;
1827 currKey = jsonPath[jsonPathType.size()-1];
1829 currVal = extractedString;
1832 if(endNumber == (
unsigned int)-1 ||
1833 endNumber <= startNumber)
1836 if(endNumber <= startNumber)
1839 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
1843 jsonPath.pop_back();
1844 jsonPathType.pop_back();
1847 if(jsonPathType[jsonPathType.size()-1] !=
'{')
1849 __COUT__ <<
"Invalid '}' position" << std::endl;
1853 jsonPath.pop_back();
1854 jsonPathType.pop_back();
1859 jsonPathType.push_back(
'[');
1860 jsonPath.push_back(
"[");
1868 if(jsonPathType[jsonPathType.size()-1] !=
'[')
1870 __COUT__ <<
"Invalid ']' position" << std::endl;
1874 currDepth = bracketCount;
1878 currVal = extractedString;
1881 if(endNumber == (
unsigned int)-1 ||
1882 endNumber <= startNumber)
1885 if(endNumber <= startNumber)
1888 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
1893 for(
unsigned int k=jsonPathType.size()-2; k<jsonPathType.size(); --k)
1894 if(jsonPathType[k] ==
'K')
1896 currKey = jsonPath[k];
1901 __COUT__ <<
"Invalid array position" << std::endl;
1906 if(jsonPathType[jsonPathType.size()-1] !=
'[')
1908 __COUT__ <<
"Invalid ']' position" << std::endl;
1912 jsonPath.pop_back();
1913 jsonPathType.pop_back();
1921 if(startNumber != (
unsigned int)-1 &&
1922 endNumber == (
unsigned int)-1)
1931 std::cout << i <<
":\t" << json[i] <<
" - ";
1933 std::cout <<
"ExtKey=";
1934 for(
unsigned int k=0;k<jsonPath.size();++k)
1935 std::cout << jsonPath[k] <<
"/";
1937 std::cout << lastPopType <<
" ";
1938 std::cout << bracketCount <<
" ";
1939 std::cout << sqBracketCount <<
" ";
1940 std::cout << inQuotes <<
" ";
1941 std::cout << newValue <<
"-";
1942 std::cout << currKey <<
"-{" << currDepth <<
"}:" ;
1943 std::cout << currVal <<
" ";
1944 std::cout << startNumber <<
"-";
1945 std::cout << endNumber <<
" ";
1977 for(
unsigned int k=0;k<keys.size();++k)
1978 if((currDepth == 1 && keys[k] == currKey) ||
1979 (currDepth > 1 && keys[k] == jsonPath[1]))
1982 if(matchedKey != (
unsigned int)-1)
1989 case CV_JSON_FILL_NAME:
1990 if(currDepth == 1) setTableName(currVal);
1992 case CV_JSON_FILL_COMMENT:
1993 if(currDepth == 1) setComment(currVal);
1995 case CV_JSON_FILL_AUTHOR:
1996 if(currDepth == 1) setAuthor(currVal);
1998 case CV_JSON_FILL_CREATION_TIME:
1999 if(currDepth == 1) setCreationTime(strtol(currVal.c_str(),0,10));
2004 case CV_JSON_FILL_DATA_SET:
2013 unsigned int col, ccnt = 0;
2014 unsigned int noc = getNumberOfColumns();
2015 for(;ccnt<noc;++ccnt)
2021 if(fillWithLooseColumnMatching_)
2033 if(getNumberOfRows() == 1)
2034 sourceColumnNames_.emplace(currKey);
2038 if(row >= getNumberOfRows())
2040 __SS__ <<
"Invalid row" << std::endl;
2041 std::cout << ss.str();
2042 throw std::runtime_error(ss.str());
2046 theDataView_[row][col] = currVal;
2051 col = (ccnt + colSpeedup) % noc;
2057 keyIsComment =
true;
2058 for(keyIsMatchIndex=0, keyIsMatchStorageIndex=0, keyIsMatchCommentIndex=0;
2059 keyIsMatchIndex<currKey.size();++keyIsMatchIndex)
2061 if(columnsInfo_[col].getStorageName()[keyIsMatchStorageIndex] ==
'_')
2062 ++keyIsMatchStorageIndex;
2063 if(currKey[keyIsMatchIndex] ==
'_')
2067 if(keyIsMatchStorageIndex >= columnsInfo_[col].getStorageName().size() ||
2068 currKey[keyIsMatchIndex] !=
2069 columnsInfo_[col].getStorageName()[keyIsMatchStorageIndex])
2078 if(keyIsComment && keyIsMatchCommentIndex < COMMENT_ALT_KEY.size())
2080 if(currKey[keyIsMatchIndex] != COMMENT_ALT_KEY[keyIsMatchCommentIndex])
2083 keyIsComment =
false;
2087 ++keyIsMatchStorageIndex;
2090 if(keyIsMatch || keyIsComment)
2095 if(getNumberOfRows())
2096 sourceColumnMissingCount_ += getNumberOfColumns() - colFoundCount;
2104 if(getNumberOfRows() == 1)
2105 sourceColumnNames_.emplace(currKey);
2109 if(row >= getNumberOfRows())
2111 __SS__ <<
"Invalid row" << std::endl;
2112 __COUT__ <<
"\n" << ss.str();
2113 throw std::runtime_error(ss.str());
2117 theDataView_[row][col] = currVal;
2123 colSpeedup = (colSpeedup + 1) % noc;
2125 if(ccnt >= getNumberOfColumns())
2127 __SS__ <<
"\n\nInvalid column in JSON source data: " <<
2128 currKey <<
" not found in column names of table named " <<
2129 getTableName() <<
"." <<
2131 __COUT__ <<
"\n" << ss.str();
2134 ++sourceColumnMismatchCount_;
2135 if(getNumberOfRows() == 1)
2136 sourceColumnNames_.emplace(currKey);
2169 bool ConfigurationView::isURIEncodedCommentTheSame(
const std::string &comment)
const
2171 std::string compareStr = decodeURIComponent(comment);
2172 return comment_ == compareStr;
2227 int ConfigurationView::fillFromCSV(
const std::string &data,
const int &dataOffset,
2228 const std::string &author)
2229 throw(std::runtime_error)
2235 int j = data.find(
',',i);
2236 int k = data.find(
';',i);
2238 bool rowWasModified;
2239 unsigned int countRowsModified = 0;
2240 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
2241 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
2244 while(k != (
int)(std::string::npos))
2246 rowWasModified =
false;
2247 if(r >= (
int)getNumberOfRows())
2251 rowWasModified =
true;
2254 while(j < k && j != (
int)(std::string::npos))
2259 if(c >= (
int)getNumberOfColumns()-2)
2262 j = data.find(
',',i);
2267 if(setURIEncodedValue(data.substr(i,j-i),r,c))
2268 rowWasModified =
true;
2271 j = data.find(
',',i);
2276 if(author !=
"" && rowWasModified)
2278 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << std::endl;
2279 setValue(author,r,authorCol);
2280 setValue(time(0),r,timestampCol);
2283 if(rowWasModified) ++countRowsModified;
2290 j = data.find(
',',i);
2291 k = data.find(
';',i);
2295 while(r < (
int)getNumberOfRows())
2298 __COUT__ <<
"Row deleted: " << (int)r << std::endl;
2299 ++countRowsModified;
2302 __COUT_INFO__ <<
"countRowsModified=" <<
2303 countRowsModified << std::endl;
2305 if(!countRowsModified)
2307 __SS__ <<
"No rows were modified! No reason to fill a view with same content." << std::endl;
2308 __COUT__ <<
"\n" << ss.str();
2315 sourceColumnNames_.clear();
2316 for(
unsigned int i=0;i<getNumberOfColumns();++i)
2317 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
2337 bool ConfigurationView::setURIEncodedValue(
const std::string &value,
const unsigned int &r,
2338 const unsigned int &c,
const std::string &author)
2340 if(!(c < columnsInfo_.size() && r < getNumberOfRows()))
2342 __SS__ <<
"Invalid row (" << (int)r <<
") col (" << (
int)c << ") requested!" <<
2343 "Number of Rows = " << getNumberOfRows() <<
2344 "Number of Columns = " << columnsInfo_.size() << std::endl;
2346 throw std::runtime_error(ss.str());
2349 std::
string valueStr = decodeURIComponent(value);
2350 std::
string originalValueStr = getValueAsString(r,c,false);
2356 if(columnsInfo_[c].getDataType() ==
ViewColumnInfo::DATATYPE_NUMBER)
2359 std::string convertedString = convertEnvVariables(valueStr);
2360 if(!isNumber(convertedString))
2362 __SS__ <<
"\tIn configuration " << tableName_
2363 <<
" at column=" << columnsInfo_[c].getName()
2364 <<
" the value set (" << convertedString <<
")"
2365 <<
" is not a number! Please fix it or change the column type..." << std::endl;
2366 throw std::runtime_error(ss.str());
2368 theDataView_[r][c] = valueStr;
2370 else if(columnsInfo_[c].getDataType() == ViewColumnInfo::DATATYPE_TIME)
2382 setValue(time_t(strtol(valueStr.c_str(),0,10)),
2386 theDataView_[r][c] = valueStr;
2388 bool rowWasModified = (originalValueStr != getValueAsString(r,c,
false));
2391 if(author !=
"" && rowWasModified)
2393 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << std::endl;
2394 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
2395 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
2396 setValue(author,r,authorCol);
2397 setValue(time(0),r,timestampCol);
2400 return rowWasModified;
2406 std::string ConfigurationView::decodeURIComponent(
const std::string &data)
2408 std::string decodeURIString(data.size(),0);
2410 for(
unsigned int i=0;i<data.size();++i,++j)
2416 decodeURIString[j] += (data[i+1]-55)*16;
2418 decodeURIString[j] += (data[i+1]-48)*16;
2422 decodeURIString[j] += (data[i+2]-55);
2424 decodeURIString[j] += (data[i+2]-48);
2429 decodeURIString[j] = data[i];
2431 decodeURIString.resize(j);
2432 return decodeURIString;
2436 void ConfigurationView::resizeDataView(
unsigned int nRows,
unsigned int nCols)
2439 theDataView_.resize(nRows, std::vector<std::string>(nCols));
2449 int ConfigurationView::addRow(
const std::string &author, std::string baseNameAutoUID)
2451 int row = getNumberOfRows();
2452 theDataView_.resize(getNumberOfRows()+1,std::vector<std::string>(getNumberOfColumns()));
2454 std::vector<std::string> defaultRowValues =
2455 getDefaultRowValues();
2459 for(
unsigned int col=0;col<getNumberOfColumns();++col)
2460 theDataView_[row][col] = defaultRowValues[col];
2464 __COUT__ <<
"Row=" << row <<
" was created!" << std::endl;
2465 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
2466 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
2467 setValue(author,row,authorCol);
2468 setValue(time(0),row,timestampCol);
2471 if(baseNameAutoUID !=
"")
2473 std::string indexSubstring =
"0";
2475 if(theDataView_.size() > 1 &&
2477 theDataView_[theDataView_.size()-2][getColUID()].find(baseNameAutoUID))
2479 indexSubstring = theDataView_[theDataView_.size()-2][getColUID()].substr(
2480 baseNameAutoUID.size());
2483 sscanf(indexSubstring.c_str(),
"%u",&index);
2485 char indexString[100];
2486 sprintf(indexString,
"%u",index);
2488 baseNameAutoUID += indexString;
2489 setValue(baseNameAutoUID,row,getColUID());
2498 void ConfigurationView::deleteRow(
int r)
2500 if(r >= (
int)getNumberOfRows())
2503 __SS__ <<
"Row " << (int)r <<
" is out of bounds (Row Count = " <<
2504 getNumberOfRows() <<
") and can not be deleted." <<
2506 throw std::runtime_error(ss.str());
2509 theDataView_.erase(theDataView_.begin()+r);
2526 const bool ConfigurationView::getChildLink(
const unsigned int& c,
bool& isGroup,
2527 std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>& linkPair)
const
2530 if(!(c < columnsInfo_.size()))
2532 __SS__ <<
"Invalid col (" << (int)c <<
") requested!" << std::endl;
2533 throw std::runtime_error(ss.str());
2540 if((isGroup = columnsInfo_[c].isChildLinkGroupID()) ||
2541 columnsInfo_[c].isChildLinkUID())
2545 linkPair.second = c;
2546 std::string index = columnsInfo_[c].getChildLinkIndex();
2551 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
2554 if(col == c)
continue;
2555 else if(columnsInfo_[col].isChildLink() &&
2556 index == columnsInfo_[col].getChildLinkIndex())
2560 linkPair.first = col;
2566 __SS__ <<
"\tIn view: " << tableName_ <<
2567 ", Can't find complete child link for column name " << columnsInfo_[c].getName() << std::endl;
2568 throw std::runtime_error(ss.str());
2571 if(!columnsInfo_[c].isChildLink())
2576 std::string index = columnsInfo_[c].getChildLinkIndex();
2581 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
2584 if(col == c)
continue;
2596 if(((columnsInfo_[col].isChildLinkUID() && !(isGroup =
false)) ||
2597 (columnsInfo_[col].isChildLinkGroupID() && (isGroup =
true)))
2598 && index == columnsInfo_[col].getChildLinkIndex())
2602 linkPair.second = col;
2608 __SS__ <<
"\tIn view: " << tableName_ <<
2609 ", Can't find complete child link id for column name " << columnsInfo_[c].getName() << std::endl;
2610 throw std::runtime_error(ss.str());
2616 bool ConfigurationView::isNumber(
const std::string& s)
const
2619 if(s.find(
"0x") == 0)
2622 for(
unsigned int i=2;i<s.size();++i)
2624 if(!((s[i] >=
'0' && s[i] <=
'9') ||
2625 (s[i] >=
'A' && s[i] <=
'F') ||
2626 (s[i] >=
'a' && s[i] <=
'f')
2635 else if(s[0] ==
'b')
2639 for(
unsigned int i=1;i<s.size();++i)
2641 if(!((s[i] >=
'0' && s[i] <=
'1')
2652 for(
unsigned int i=0;i<s.size();++i)
2653 if(!((s[i] >=
'0' && s[i] <=
'9') ||
2673 std::string ots_demangle(
const char* name) {
2678 std::unique_ptr<char, void(*)(void*)> res {
2679 abi::__cxa_demangle(name, NULL, NULL, &status),
2683 return (status==0) ? res.get() : name ;
2689 std::string ots_demangle(
const char* name) {