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 colPriority_ (INVALID),
29 fillWithLooseColumnMatching_(false),
30 sourceColumnMismatchCount_ (0),
31 sourceColumnMissingCount_ (0)
35 ConfigurationView::~ConfigurationView(
void)
44 __SS__ <<
"Invalid use of operator=... Should not directly copy a ConfigurationView. Please use ConfigurationView::copy(sourceView,author,comment)";
45 throw std::runtime_error(ss.str());
51 const std::string &author)
53 tableName_ = src.tableName_;
54 version_ = destinationVersion;
55 comment_ = src.comment_;
58 lastAccessTime_ = time(0);
59 columnsInfo_ = src.columnsInfo_;
60 theDataView_ = src.theDataView_;
61 sourceColumnNames_ = src.sourceColumnNames_;
73 void ConfigurationView::init(
void)
79 std::set<std::string> colNameSet;
80 std::string capsColName, colName;
81 for(
auto &colInfo: columnsInfo_)
83 colName = colInfo.getStorageName();
84 if(colName ==
"COMMENT_DESCRIPTION")
87 for(
unsigned int i=0;i<colName.size(); ++i)
89 if(colName[i] ==
'_')
continue;
90 capsColName += colName[i];
93 colNameSet.emplace(capsColName);
96 if(colNameSet.size() != columnsInfo_.size())
98 __SS__ <<
"Configuration Error:\t" <<
99 " Columns names must be unique! There are " << columnsInfo_.size() <<
100 " columns and the unique name count is " << colNameSet.size() << std::endl;
101 __COUT_ERR__ <<
"\n" << ss.str();
103 throw std::runtime_error(ss.str());
109 getOrInitColStatus();
114 getOrInitColPriority();
121 if((colPos = findColByType(ViewColumnInfo::TYPE_COMMENT)) != INVALID)
123 if(columnsInfo_[colPos].getName() !=
"CommentDescription")
125 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
126 " data type column must have name=" <<
127 "CommentDescription" << std::endl;
128 __COUT_ERR__ <<
"\n" << ss.str();
129 throw std::runtime_error(ss.str());
132 if(findColByType(ViewColumnInfo::TYPE_COMMENT,colPos+1) != INVALID)
134 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
135 " data type in column " <<
136 columnsInfo_[colPos].getName() <<
137 " is repeated. This is not allowed." << std::endl;
138 __COUT_ERR__ <<
"\n" << ss.str();
139 throw std::runtime_error(ss.str());
142 if(colPos != getNumberOfColumns()-3)
144 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
145 " data type column must be 3rd to last (in column " <<
146 getNumberOfColumns()-3 <<
")." << std::endl;
147 __COUT_ERR__ <<
"\n" << ss.str();
148 throw std::runtime_error(ss.str());
153 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_COMMENT <<
154 " data type column " <<
" is missing. This is not allowed." << std::endl;
155 __COUT_ERR__ <<
"\n" << ss.str();
156 throw std::runtime_error(ss.str());
160 if((colPos = findColByType(ViewColumnInfo::TYPE_AUTHOR)) != INVALID)
162 if(findColByType(ViewColumnInfo::TYPE_AUTHOR,colPos+1) != INVALID)
164 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_AUTHOR <<
165 " data type in column " <<
166 columnsInfo_[colPos].getName() <<
167 " is repeated. This is not allowed." << std::endl;
168 __COUT_ERR__ <<
"\n" << ss.str();
169 throw std::runtime_error(ss.str());
172 if(colPos != getNumberOfColumns()-2)
174 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_AUTHOR <<
175 " data type column must be 2nd to last (in column " <<
176 getNumberOfColumns()-2 <<
")." << std::endl;
177 __COUT_ERR__ <<
"\n" << ss.str();
178 throw std::runtime_error(ss.str());
183 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_AUTHOR <<
184 " data type column " <<
" is missing. This is not allowed." << std::endl;
185 __COUT_ERR__ <<
"\n" << ss.str();
186 throw std::runtime_error(ss.str());
190 if((colPos = findColByType(ViewColumnInfo::TYPE_TIMESTAMP)) != INVALID)
192 if(findColByType(ViewColumnInfo::TYPE_TIMESTAMP,colPos+1) != INVALID)
194 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_TIMESTAMP <<
195 " data type in column " <<
196 columnsInfo_[colPos].getName() <<
" is repeated. This is not allowed." <<
198 __COUT_ERR__ <<
"\n" << ss.str();
199 throw std::runtime_error(ss.str());
202 if(colPos != getNumberOfColumns()-1)
204 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_TIMESTAMP <<
205 " data type column must be last (in column " <<
206 getNumberOfColumns()-1 <<
")." << std::endl;
207 __COUT_ERR__ <<
"\n" << ss.str();
208 throw std::runtime_error(ss.str());
213 __SS__ <<
"Configuration Error:\t" << ViewColumnInfo::TYPE_TIMESTAMP <<
214 " data type column " <<
" is missing. This is not allowed." << std::endl;
215 __COUT_ERR__ <<
"\n" << ss.str();
216 throw std::runtime_error(ss.str());
222 std::set<std::string > uidSet;
223 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
225 if(uidSet.find(theDataView_[row][colUID_]) != uidSet.end())
227 __SS__ << (
"Entries in UID are not unique. Specifically at row=" +
228 std::to_string(row) +
" value=" + theDataView_[row][colUID_])<< std::endl;
229 __COUT_ERR__ <<
"\n" << ss.str();
230 throw std::runtime_error(ss.str());
233 if(theDataView_[row][colUID_].size() == 0)
235 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' " <<
236 " was identified. UIDs must contain at least 1 character." <<
238 throw std::runtime_error(ss.str());
241 for(
unsigned int i=0;i<theDataView_[row][colUID_].size();++i)
243 (theDataView_[row][colUID_][i] >=
'A' && theDataView_[row][colUID_][i] <=
'Z') ||
244 (theDataView_[row][colUID_][i] >=
'a' && theDataView_[row][colUID_][i] <=
'z') ||
245 (theDataView_[row][colUID_][i] >=
'0' && theDataView_[row][colUID_][i] <=
'9') ||
246 (theDataView_[row][colUID_][i] ==
'-' ||
247 theDataView_[row][colUID_][i] <=
'_')
250 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' " <<
251 " was identified. UIDs must contain only letters, numbers," <<
252 "dashes, and underscores." << std::endl;
253 throw std::runtime_error(ss.str());
256 uidSet.insert(theDataView_[row][colUID_]);
258 if(uidSet.size() != getNumberOfRows())
260 __SS__ <<
"Entries in UID are not unique!" <<
261 "There are " << getNumberOfRows() <<
262 " rows and the unique UID count is " << uidSet.size() << std::endl;
263 __COUT_ERR__ <<
"\n" << ss.str();
264 throw std::runtime_error(ss.str());
268 colPos = (
unsigned int)-1;
269 while((colPos = findColByType(ViewColumnInfo::TYPE_UNIQUE_DATA,colPos+1)) != INVALID)
271 std::set<std::string > uDataSet;
272 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
274 if(uDataSet.find(theDataView_[row][colPos]) != uDataSet.end())
276 __SS__ <<
"Entries in Unique Data column " <<
277 columnsInfo_[colPos].getName() <<
278 (
" are not unique. Specifically at row=" +
279 std::to_string(row) +
" value=" + theDataView_[row][colPos]) <<
281 __COUT_ERR__ <<
"\n" << ss.str();
282 throw std::runtime_error(ss.str());
284 uDataSet.insert(theDataView_[row][colPos]);
286 if(uDataSet.size() != getNumberOfRows())
288 __SS__ <<
"Entries in Unique Data column " <<
289 columnsInfo_[colPos].getName() <<
" are not unique!" <<
290 "There are " << getNumberOfRows() <<
291 " rows and the unique data count is " << uDataSet.size() << std::endl;
292 __COUT_ERR__ <<
"\n" << ss.str();
293 throw std::runtime_error(ss.str());
297 auto rowDefaults = getDefaultRowValues();
304 std::set<std::string> groupIdIndexes, childLinkIndexes, childLinkIdLabels;
305 unsigned int groupIdIndexesCount = 0, childLinkIndexesCount = 0, childLinkIdLabelsCount = 0;
306 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
308 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
310 const std::vector<std::string>& theDataChoices =
311 columnsInfo_[col].getDataChoices();
314 if(theDataChoices.size() && theDataChoices[0] ==
319 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
323 if(theDataView_[row][col] == rowDefaults[col])
326 for(
const auto &choice:theDataChoices)
328 if(theDataView_[row][col] == choice)
336 __SS__ <<
"Configuration Error:\t'" << theDataView_[row][col] <<
"' in column " <<
337 columnsInfo_[col].getName() <<
" is not a valid Fixed Choice option. " <<
338 "Possible values are as follows: ";
340 for(
unsigned int i = 0; i < columnsInfo_[col].getDataChoices().size(); ++i)
343 ss << columnsInfo_[col].getDataChoices()[i];
345 ss <<
"." << std::endl;
346 __COUT_ERR__ <<
"\n" << ss.str();
347 throw std::runtime_error(ss.str());
351 if(columnsInfo_[col].isChildLink())
355 const std::vector<std::string>& theDataChoices =
356 columnsInfo_[col].getDataChoices();
359 if(!theDataChoices.size() ||
360 theDataChoices[0] ==
"arbitraryBool=1")
364 bool skipOne = (theDataChoices.size() &&
365 theDataChoices[0] ==
"arbitraryBool=0");
369 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
374 for(
const auto &choice:theDataChoices)
376 if(skipOne && !hasSkipped) {hasSkipped =
true;
continue;}
378 if(theDataView_[row][col] == choice)
386 __SS__ <<
"Configuration Error:\t'" << theDataView_[row][col] <<
"' in column " <<
387 columnsInfo_[col].getName() <<
" is not a valid Fixed Choice option. " <<
388 "Possible values are as follows: ";
390 for(
unsigned int i = skipOne?1:0; i < columnsInfo_[col].getDataChoices().size(); ++i)
392 if(i == 1 + (skipOne?1:0)) ss <<
", ";
393 ss << columnsInfo_[col].getDataChoices()[i];
395 ss <<
"." << std::endl;
396 __COUT_ERR__ <<
"\n" << ss.str();
397 throw std::runtime_error(ss.str());
401 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_ON_OFF)
402 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
404 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" || theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
405 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_ON;
406 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"off" || theDataView_[row][col] ==
"Off" || theDataView_[row][col] ==
"OFF")
407 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_OFF;
410 __SS__ <<
"Configuration Error:\t" << theDataView_[row][col] <<
" in column " <<
411 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;
412 __COUT_ERR__ <<
"\n" << ss.str();
413 throw std::runtime_error(ss.str());
416 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_TRUE_FALSE)
417 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
419 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" || theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
420 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_TRUE;
421 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"false" || theDataView_[row][col] ==
"False" || theDataView_[row][col] ==
"FALSE")
422 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_FALSE;
425 __SS__ <<
"Configuration Error:\t" << theDataView_[row][col] <<
" in column " <<
426 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;
427 __COUT_ERR__ <<
"\n" << ss.str();
428 throw std::runtime_error(ss.str());
431 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_YES_NO)
432 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
434 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" || theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
435 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_YES;
436 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"no" || theDataView_[row][col] ==
"No" || theDataView_[row][col] ==
"NO")
437 theDataView_[row][col] = ViewColumnInfo::TYPE_VALUE_NO;
440 __SS__ <<
"Configuration Error:\t" << theDataView_[row][col] <<
" in column " <<
441 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;
442 __COUT_ERR__ <<
"\n" << ss.str();
443 throw std::runtime_error(ss.str());
446 else if(columnsInfo_[col].isGroupID())
448 colLinkGroupIDs_[columnsInfo_[col].getChildLinkIndex()] = col;
450 groupIdIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
451 ++groupIdIndexesCount;
453 else if(columnsInfo_[col].isChildLink())
456 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
457 if(theDataView_[row][col] ==
"NoLink" ||
458 theDataView_[row][col] ==
"No_Link" ||
459 theDataView_[row][col] ==
"NOLINK" ||
460 theDataView_[row][col] ==
"NO_LINK" ||
461 theDataView_[row][col] ==
"Nolink" ||
462 theDataView_[row][col] ==
"nolink" ||
463 theDataView_[row][col] ==
"noLink")
464 theDataView_[row][col] = ViewColumnInfo::DATATYPE_LINK_DEFAULT;
467 childLinkIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
468 ++childLinkIndexesCount;
471 if(columnsInfo_[col].getDataType() != ViewColumnInfo::DATATYPE_STRING)
473 __SS__ <<
"Configuration Error:\t" <<
"Column " << col <<
474 " with name " << columnsInfo_[col].getName() <<
475 " is a Child Link column and has an illegal data type of '" <<
476 columnsInfo_[col].getDataType() <<
477 "'. The data type for Child Link columns must be " <<
478 ViewColumnInfo::DATATYPE_STRING << std::endl;
479 __COUT_ERR__ <<
"\n" << ss.str();
480 throw std::runtime_error(ss.str());
484 else if(columnsInfo_[col].isChildLinkUID() ||
485 columnsInfo_[col].isChildLinkGroupID())
488 childLinkIdLabels.emplace(columnsInfo_[col].getChildLinkIndex());
489 ++childLinkIdLabelsCount;
492 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
493 if(theDataView_[row][col] ==
"")
494 theDataView_[row][col] = rowDefaults[col];
500 if(groupIdIndexes.size() != groupIdIndexesCount)
502 __SS__ << (
"GroupId Labels are not unique!") <<
503 "There are " << groupIdIndexesCount <<
504 " GroupId Labels and the unique count is " << groupIdIndexes.size() << std::endl;
505 __COUT_ERR__ <<
"\n" << ss.str();
506 throw std::runtime_error(ss.str());
508 if(childLinkIndexes.size() != childLinkIndexesCount)
510 __SS__ << (
"Child Link Labels are not unique!") <<
511 "There are " << childLinkIndexesCount <<
512 " Child Link Labels and the unique count is " << childLinkIndexes.size() << std::endl;
513 __COUT_ERR__ <<
"\n" << ss.str();
514 throw std::runtime_error(ss.str());
516 if(childLinkIdLabels.size() != childLinkIdLabelsCount)
518 __SS__ << (
"Child Link ID Labels are not unique!") <<
519 "There are " << childLinkIdLabelsCount <<
520 " Child Link ID Labels and the unique count is " << childLinkIdLabels.size() << std::endl;
521 __COUT_ERR__ <<
"\n" << ss.str();
522 throw std::runtime_error(ss.str());
528 __COUT__ <<
"Error occured in ConfigurationView::init() for version=" << version_ << std::endl;
537 void ConfigurationView::getValue(std::string& value,
unsigned int row,
unsigned int col,
bool doConvertEnvironmentVariables)
const
539 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
541 __SS__ <<
"Invalid row col requested" << std::endl;
545 value = validateValueForColumn(theDataView_[row][col],col,doConvertEnvironmentVariables);
554 std::string ConfigurationView::validateValueForColumn(
const std::string& value,
555 unsigned int col,
bool doConvertEnvironmentVariables)
const
557 if(col >= columnsInfo_.size())
559 __SS__ <<
"Invalid col requested" << std::endl;
563 std::string retValue;
565 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING)
566 retValue = doConvertEnvironmentVariables?StringMacros::convertEnvironmentVariables(value):value;
567 else if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_TIME)
571 strtol((doConvertEnvironmentVariables?StringMacros::convertEnvironmentVariables(value):value).c_str(),
574 ::localtime_r(×tamp, &tmstruct);
575 ::strftime(&retValue[0], 30,
"%c %Z", &tmstruct);
576 retValue.resize(strlen(retValue.c_str()));
580 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
581 <<
" in configuration " << tableName_
582 <<
" at column=" << columnsInfo_[col].getName()
583 <<
" for getValue with type '" << StringMacros::demangleTypeName(
typeid(retValue).name())
596 std::string ConfigurationView::getValueAsString(
unsigned int row,
unsigned int col,
597 bool doConvertEnvironmentVariables)
const
599 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
601 __SS__ << (
"Invalid row col requested") << std::endl;
602 __COUT_ERR__ << ss.str();
603 throw std::runtime_error(ss.str());
608 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_ON_OFF)
610 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" || theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
611 return ViewColumnInfo::TYPE_VALUE_ON;
613 return ViewColumnInfo::TYPE_VALUE_OFF;
615 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_TRUE_FALSE)
617 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" || theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
618 return ViewColumnInfo::TYPE_VALUE_TRUE;
620 return ViewColumnInfo::TYPE_VALUE_FALSE;
622 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_YES_NO)
624 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" || theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
625 return ViewColumnInfo::TYPE_VALUE_YES;
627 return ViewColumnInfo::TYPE_VALUE_NO;
631 return doConvertEnvironmentVariables?StringMacros::convertEnvironmentVariables(theDataView_[row][col]):
632 theDataView_[row][col];
642 std::string ConfigurationView::getEscapedValueAsString(
unsigned int row,
unsigned int col,
643 bool doConvertEnvironmentVariables)
const
645 std::string val = getValueAsString(row,col,doConvertEnvironmentVariables);
646 std::string retVal =
"";
647 retVal.reserve(val.size());
648 for(
unsigned int i=0;i<val.size();++i)
652 else if(val[i] ==
'\t')
654 else if(val[i] ==
'\r')
671 void ConfigurationView::setValue(
const std::string &value,
unsigned int row,
unsigned int col)
673 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
675 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << std::endl;
676 throw std::runtime_error(ss.str());
679 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING)
680 theDataView_[row][col] = value;
684 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
685 <<
" in configuration " << tableName_
686 <<
" at column=" << columnsInfo_[col].getName()
687 <<
" for setValue with type '" << StringMacros::demangleTypeName(
typeid(value).name())
689 throw std::runtime_error(ss.str());
692 void ConfigurationView::setValue(
const char *value,
unsigned int row,
unsigned int col)
693 { setValue(std::string(value),row,col); }
698 void ConfigurationView::setValueAsString(
const std::string &value,
unsigned int row,
unsigned int col)
700 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
702 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << std::endl;
703 throw std::runtime_error(ss.str());
706 theDataView_[row][col] = value;
712 const unsigned int ConfigurationView::getOrInitColUID(
void)
714 if(colUID_ != INVALID)
return colUID_;
717 colUID_ = findColByType(ViewColumnInfo::TYPE_UID);
718 if(colUID_ == INVALID)
720 __COUT__ <<
"Column Types: " << std::endl;
721 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
722 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
723 __SS__ <<
"\tMissing UID Column in table named '" << tableName_ <<
"'" << std::endl;
724 __COUT_ERR__ <<
"\n" << ss.str() << std::endl;
725 throw std::runtime_error(ss.str());
733 const unsigned int ConfigurationView::getColUID(
void)
const
735 if(colUID_ != INVALID)
return colUID_;
737 __COUT__ <<
"Column Types: " << std::endl;
738 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
739 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
741 __SS__ << (
"Missing UID Column in config named " + tableName_ +
742 ". (Possibly ConfigurationView was just not initialized?" +
743 "This is the const call so can not alter class members)") << std::endl;
744 __COUT_ERR__ <<
"\n" << ss.str() << std::endl;
745 throw std::runtime_error(ss.str());
751 const unsigned int ConfigurationView::getOrInitColStatus(
void)
753 if(colStatus_ != INVALID)
return colStatus_;
756 colStatus_ = findCol(ViewColumnInfo::COL_NAME_STATUS);
757 if(colStatus_ == INVALID)
759 __SS__ <<
"\tMissing " << ViewColumnInfo::COL_NAME_STATUS <<
" Column in table named '" << tableName_ <<
"'" << std::endl;
760 ss <<
"Column Types: " << std::endl;
761 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
762 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
765 throw std::runtime_error(ss.str());
773 const unsigned int ConfigurationView::getOrInitColPriority(
void)
775 if(colPriority_ != INVALID)
return colPriority_;
778 colPriority_ = findCol(ViewColumnInfo::COL_NAME_PRIORITY);
779 if(colPriority_ == INVALID)
781 __SS__ <<
"\tMissing " << ViewColumnInfo::COL_NAME_PRIORITY <<
782 " Column in table named '" << tableName_ <<
"'" << std::endl;
783 ss <<
"Column Types: " << std::endl;
784 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
785 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
788 throw std::runtime_error(ss.str());
797 const unsigned int ConfigurationView::getColStatus(
void)
const
799 if(colStatus_ != INVALID)
return colStatus_;
801 __COUT__ <<
"Column Types: " << std::endl;
802 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
803 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
805 __SS__ <<
"Missing " << ViewColumnInfo::COL_NAME_STATUS <<
" Column in config named " << tableName_ <<
806 ". (Possibly ConfigurationView was just not initialized?" <<
807 "This is the const call so can not alter class members)" << std::endl;
808 __COUT_ERR__ <<
"\n" << ss.str() << std::endl;
809 throw std::runtime_error(ss.str());
816 const unsigned int ConfigurationView::getColPriority(
void)
const
818 if(colPriority_ != INVALID)
return colPriority_;
820 __COUT__ <<
"Column Types: " << std::endl;
821 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
822 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
824 __SS__ <<
"Missing " << ViewColumnInfo::COL_NAME_PRIORITY <<
" Column in config named " << tableName_ <<
825 ". (Possibly ConfigurationView was just not initialized?" <<
826 "This is the const call so can not alter class members)" << std::endl;
827 __COUT_ERR__ <<
"\n" << ss.str() << std::endl;
828 throw std::runtime_error(ss.str());
834 void ConfigurationView::addRowToGroup(
const unsigned int &row,
835 const unsigned int &col,
836 const std::string &groupID)
839 if(isEntryInGroupCol(row,col,groupID))
841 __SS__ <<
"GroupID (" << groupID <<
842 ") added to row (" << row
843 <<
" is already present!" << std::endl;
844 throw std::runtime_error(ss.str());
852 if(getDataView()[row][col] ==
"" ||
853 getDataView()[row][col] == getDefaultRowValues()[col])
859 groupID +
" | " + getDataView()[row][col],
870 bool ConfigurationView::removeRowFromGroup(
const unsigned int &row,
871 const unsigned int &col,
872 const std::string &groupNeedle,
873 bool deleteRowIfNoGroupLeft)
875 __COUT__ <<
"groupNeedle " << groupNeedle << std::endl;
876 std::set<std::string> groupIDList;
877 if(!isEntryInGroupCol(row,col,groupNeedle,&groupIDList))
879 __SS__ <<
"GroupID (" << groupNeedle <<
880 ") removed from row (" << row
881 <<
") was already removed!" << std::endl;
882 throw std::runtime_error(ss.str());
889 std::string newValue =
"";
890 unsigned int cnt = 0;
891 for(
const auto & groupID : groupIDList)
894 if(groupID == groupNeedle)
continue;
896 if(cnt) newValue +=
" | ";
900 bool wasDeleted =
false;
901 if(deleteRowIfNoGroupLeft && newValue ==
"")
903 __COUT__ <<
"Delete row since it no longer part of any group." << std::endl;
908 setValue(newValue,row,col);
921 bool ConfigurationView::isEntryInGroup(
const unsigned int &r,
922 const std::string &childLinkIndex,
923 const std::string &groupNeedle)
const
925 unsigned int c = getColLinkGroupID(childLinkIndex);
927 return isEntryInGroupCol(r,c,groupNeedle);
940 bool ConfigurationView::isEntryInGroupCol(
const unsigned int &r,
941 const unsigned int &c,
const std::string &groupNeedle,
942 std::set<std::string> *groupIDList)
const
951 for(;j<theDataView_[r][c].size();++j)
952 if((theDataView_[r][c][j] ==
' ' ||
953 theDataView_[r][c][j] ==
'|')
956 else if((theDataView_[r][c][j] ==
' ' ||
957 theDataView_[r][c][j] ==
'|')
960 if(groupIDList) groupIDList->emplace(theDataView_[r][c].substr(i,j-i));
964 if(groupNeedle == theDataView_[r][c].substr(i,j-i))
976 if(groupIDList) groupIDList->emplace(theDataView_[r][c].substr(i,j-i));
980 if(groupNeedle == theDataView_[r][c].substr(i,j-i))
996 std::set<std::string> ConfigurationView::getSetOfGroupIDs(
const std::string &childLinkIndex,
997 unsigned int r)
const
999 unsigned int c = getColLinkGroupID(childLinkIndex);
1003 std::set<std::string> retSet;
1008 if(r != (
unsigned int)-1)
1010 if(r >= getNumberOfRows())
1012 __SS__ <<
"Invalid row requested!" << std::endl;
1013 throw std::runtime_error(ss.str());
1016 StringMacros::getSetFromString(theDataView_[r][c],retSet);
1044 for(r=0;r<getNumberOfRows();++r)
1046 StringMacros::getSetFromString(theDataView_[r][c],retSet);
1092 const unsigned int ConfigurationView::getColLinkGroupID(
const std::string &childLinkIndex)
const
1094 std::map<std::string, unsigned int>::const_iterator it = colLinkGroupIDs_.find(childLinkIndex);
1096 colLinkGroupIDs_.end())
1099 __COUT__ <<
"Existing Column Types: " << std::endl;
1100 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
1101 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << std::endl;
1103 __SS__ << (
"Incompatible table for this group link. Table '" +
1104 tableName_ +
"' is missing a GroupID column with data type '" +
1105 (ViewColumnInfo::TYPE_START_GROUP_ID +
"-" + childLinkIndex) +
1106 "'." ) << std::endl;
1107 __COUT_ERR__ <<
"\n" << ss.str();
1108 throw std::runtime_error(ss.str());
1112 unsigned int ConfigurationView::findRow(
unsigned int col,
const std::string& value,
unsigned int offsetRow)
const
1114 for(
unsigned int row=offsetRow; row<theDataView_.size(); ++row)
1116 if(theDataView_[row][col] == value)
1120 __SS__ <<
"\tIn view: " << tableName_
1121 <<
", Can't find value=" << value
1122 <<
" in column named " << columnsInfo_[col].getName()
1123 <<
" with type=" << columnsInfo_[col].getType()
1128 throw std::runtime_error(ss.str());
1132 unsigned int ConfigurationView::findRowInGroup(
unsigned int col,
const std::string& value,
1133 const std::string &groupId,
const std::string &childLinkIndex,
unsigned int offsetRow)
const
1135 unsigned int groupIdCol = getColLinkGroupID(childLinkIndex);
1136 for(
unsigned int row=offsetRow; row<theDataView_.size(); ++row)
1138 if(theDataView_[row][col] == value &&
1139 isEntryInGroupCol(row,groupIdCol,groupId))
1143 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find in group the value=" <<
1144 value <<
" in column named '" <<
1145 columnsInfo_[col].getName() <<
"' with type=" <<
1146 columnsInfo_[col].getType() <<
" and GroupID: '" <<
1147 groupId <<
"' in column '" << groupIdCol <<
1148 "' with GroupID child link index '" << childLinkIndex <<
"'" << std::endl;
1152 throw std::runtime_error(ss.str());
1158 unsigned int ConfigurationView::findCol(
const std::string& name)
const
1160 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
1161 if(columnsInfo_[col].getName() == name)
1164 __SS__ <<
"\tIn view: " << tableName_ <<
1165 ", Can't find column named '" << name <<
"'" << std::endl;
1166 ss <<
"Existing columns:\n";
1167 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
1168 ss <<
"\t" << columnsInfo_[col].getName() <<
"\n";
1169 throw std::runtime_error(ss.str());
1175 unsigned int ConfigurationView::findColByType(
const std::string& type,
int startingCol)
const
1177 for(
unsigned int col=startingCol; col<columnsInfo_.size(); ++col)
1178 if(columnsInfo_[col].getType() == type)
1186 const std::string& ConfigurationView::getUniqueStorageIdentifier(
void)
const
1188 return uniqueStorageIdentifier_;
1192 const std::string& ConfigurationView::getTableName(
void)
const
1204 const std::string& ConfigurationView::getComment(
void)
const
1210 const std::string& ConfigurationView::getAuthor(
void)
const
1216 const time_t& ConfigurationView::getCreationTime(
void)
const
1218 return creationTime_;
1222 const time_t& ConfigurationView::getLastAccessTime(
void)
const
1224 return lastAccessTime_;
1228 const bool& ConfigurationView::getLooseColumnMatching(
void)
const
1230 return fillWithLooseColumnMatching_;
1235 const unsigned int ConfigurationView::getDataColumnSize(
void)
const
1238 if(!getNumberOfRows())
return getNumberOfColumns();
1239 return theDataView_[0].size();
1245 const unsigned int& ConfigurationView::getSourceColumnMismatch(
void)
const
1247 return sourceColumnMismatchCount_;
1253 const unsigned int& ConfigurationView::getSourceColumnMissing(
void)
const
1255 return sourceColumnMissingCount_;
1261 const std::set<std::string>& ConfigurationView::getSourceColumnNames(
void)
const
1263 return sourceColumnNames_;
1267 std::set<std::string> ConfigurationView::getColumnNames(
void)
const
1269 std::set<std::string> retSet;
1270 for(
auto &colInfo: columnsInfo_)
1271 retSet.emplace(colInfo.getName());
1276 std::set<std::string> ConfigurationView::getColumnStorageNames(
void)
const
1278 std::set<std::string> retSet;
1279 for(
auto &colInfo: columnsInfo_)
1280 retSet.emplace(colInfo.getStorageName());
1285 std::vector<std::string> ConfigurationView::getDefaultRowValues(
void)
const
1287 std::vector<std::string> retVec;
1290 for(
unsigned int col=0;col<getNumberOfColumns();++col)
1297 if(columnsInfo_[col].isChildLink())
1299 const std::vector<std::string>& theDataChoices =
1300 columnsInfo_[col].getDataChoices();
1303 if(!theDataChoices.size() ||
1304 theDataChoices[0] ==
"arbitraryBool=1")
1305 retVec.push_back(columnsInfo_[col].getDefaultValue());
1308 bool skipOne = (theDataChoices.size() &&
1309 theDataChoices[0] ==
"arbitraryBool=0");
1314 bool foundDefault =
false;
1316 for(
const auto &choice:theDataChoices)
1317 if(skipOne && !hasSkipped) {hasSkipped =
true;
continue;}
1318 else if(choice == columnsInfo_[col].getDefaultValue())
1320 foundDefault =
true;
1325 if(!foundDefault && theDataChoices.size() > (skipOne?1:0))
1326 retVec.push_back(theDataChoices[(skipOne?1:0)]);
1328 retVec.push_back(columnsInfo_[col].getDefaultValue());
1332 retVec.push_back(columnsInfo_[col].getDefaultValue());
1339 unsigned int ConfigurationView::getNumberOfRows(
void)
const
1341 return theDataView_.size();
1345 unsigned int ConfigurationView::getNumberOfColumns(
void)
const
1347 return columnsInfo_.size();
1351 const ConfigurationView::DataView& ConfigurationView::getDataView(
void)
const
1353 return theDataView_;
1363 const std::vector<ViewColumnInfo>& ConfigurationView::getColumnsInfo (
void)
const
1365 return columnsInfo_;
1369 std::vector<ViewColumnInfo>* ConfigurationView::getColumnsInfoP(
void)
1371 return &columnsInfo_;
1374 const ViewColumnInfo& ConfigurationView::getColumnInfo(
unsigned int column)
const
1376 if(column >= columnsInfo_.size())
1378 std::stringstream errMsg;
1379 errMsg << __COUT_HDR_FL__ <<
"\nCan't find column " << column <<
1380 "\n\n\n\nThe column info is likely missing due to incomplete Configuration View filling.\n\n"
1382 throw std::runtime_error(errMsg.str().c_str());
1384 return columnsInfo_[column];
1389 void ConfigurationView::setUniqueStorageIdentifier(
const std::string &storageUID)
1391 uniqueStorageIdentifier_ = storageUID;
1395 void ConfigurationView::setTableName(
const std::string &name)
1401 void ConfigurationView::setComment(
const std::string &comment)
1407 void ConfigurationView::setURIEncodedComment(
const std::string &uriComment)
1409 comment_ = StringMacros::decodeURIComponent(uriComment);
1413 void ConfigurationView::setAuthor(
const std::string &author)
1419 void ConfigurationView::setCreationTime(time_t t)
1425 void ConfigurationView::setLastAccessTime(time_t t)
1427 lastAccessTime_ = t;
1431 void ConfigurationView::setLooseColumnMatching(
bool setValue)
1433 fillWithLooseColumnMatching_ = setValue;
1437 void ConfigurationView::reset (
void)
1442 columnsInfo_.clear();
1443 theDataView_.clear();
1447 void ConfigurationView::print (std::ostream &out)
const
1449 out <<
"==============================================================================" << std::endl;
1450 out <<
"Print: " << tableName_ <<
" Version: " << version_ <<
" Comment: " << comment_ <<
1451 " Author: " << author_ <<
" Creation Time: " << ctime(&creationTime_) << std::endl;
1452 out <<
"\t\tNumber of Cols " << getNumberOfColumns() << std::endl;
1453 out <<
"\t\tNumber of Rows " << getNumberOfRows() << std::endl;
1455 out <<
"Columns:\t";
1456 for(
int i=0;i<(int)columnsInfo_.size();++i)
1457 out << i <<
":" << columnsInfo_[i].getName() <<
":" << columnsInfo_[i].getStorageName() <<
":" << columnsInfo_[i].getDataType() <<
"\t ";
1460 out <<
"Rows:" << std::endl;
1463 for(
int r=0;r<(int)getNumberOfRows();++r)
1465 out << (int)r <<
":\t";
1466 for(
int c=0;c<(int)getNumberOfColumns();++c)
1468 out << (int)c <<
":";
1471 if(columnsInfo_[c].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
1473 int choiceIndex = -1;
1474 std::vector<std::string> choices = columnsInfo_[c].getDataChoices();
1475 val = StringMacros::convertEnvironmentVariables(theDataView_[r][c]);
1477 if(val == columnsInfo_[c].getDefaultValue())
1481 for(
int i=0;i<(int)choices.size();++i)
1482 if(val == choices[i])
1486 out <<
"ChoiceIndex=" << choiceIndex <<
":";
1490 out << theDataView_[r][c];
1511 void ConfigurationView::printJSON (std::ostream &out)
const
1514 out <<
"\"NAME\" : \"" << tableName_ <<
"\",\n";
1518 out <<
"\"COMMENT\" : ";
1524 for(
unsigned int i=0;i<val.size();++i)
1529 else if(val[i] ==
'\t')
1531 else if(val[i] ==
'\r')
1544 out <<
"\"AUTHOR\" : \"" << author_ <<
"\",\n";
1545 out <<
"\"CREATION_TIME\" : " << creationTime_ <<
",\n";
1552 out <<
"\"COL_TYPES\" : {\n";
1553 for(
int c=0;c<(int)getNumberOfColumns();++c)
1555 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1556 out <<
"\"" << columnsInfo_[c].getDataType() <<
"\"";
1557 if(c+1 < (
int)getNumberOfColumns())
1563 out <<
"\"DATA_SET\" : [\n";
1565 for(
int r=0;r<(int)getNumberOfRows();++r)
1568 for(
int c=0;c<(int)getNumberOfColumns();++c)
1570 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1572 out <<
"\"" << getEscapedValueAsString(r,c,
false) <<
"\"";
1574 if(c+1 < (
int)getNumberOfColumns())
1579 if(r+1 < (
int)getNumberOfRows())
1591 std::string restoreJSONStringEntities(
const std::string &str)
1593 unsigned int sz = str.size();
1596 std::stringstream retStr;
1604 retStr <<
'\n'; ++i;
break;
1606 retStr <<
'"'; ++i;
break;
1608 retStr <<
'\t'; ++i;
break;
1610 retStr <<
'\r'; ++i;
break;
1612 retStr <<
'\\'; ++i;
break;
1620 retStr << str[sz-1];
1622 return retStr.str();
1634 int ConfigurationView::fillFromJSON(
const std::string &json)
1636 std::vector<std::string> keys;
1637 keys.push_back (
"NAME");
1638 keys.push_back (
"COMMENT");
1639 keys.push_back (
"AUTHOR");
1640 keys.push_back (
"CREATION_TIME");
1642 keys.push_back (
"DATA_SET");
1645 CV_JSON_FILL_COMMENT,
1646 CV_JSON_FILL_AUTHOR,
1647 CV_JSON_FILL_CREATION_TIME,
1649 CV_JSON_FILL_DATA_SET
1654 sourceColumnMismatchCount_ = 0;
1655 sourceColumnMissingCount_ = 0;
1656 sourceColumnNames_.clear();
1657 unsigned int colFoundCount = 0;
1659 unsigned int row = -1;
1660 unsigned int colSpeedup = 0;
1661 unsigned int startString, startNumber, endNumber = -1;
1662 unsigned int bracketCount = 0;
1663 unsigned int sqBracketCount = 0;
1667 bool isDataArray = 0;
1668 bool keyIsMatch, keyIsComment;
1669 unsigned int keyIsMatchIndex, keyIsMatchStorageIndex, keyIsMatchCommentIndex;
1670 const std::string COMMENT_ALT_KEY =
"COMMENT";
1672 std::string extractedString =
"", currKey =
"", currVal =
"";
1673 unsigned int currDepth;
1675 std::vector<std::string> jsonPath;
1676 std::vector<char> jsonPathType;
1677 char lastPopType =
'_';
1679 unsigned int matchedKey = -1;
1680 unsigned int lastCol = -1;
1684 for(;i<json.size();++i)
1689 if(i-1 < json.size() &&
1690 json[i-1] ==
'\\')
break;
1692 inQuotes = !inQuotes;
1697 extractedString = restoreJSONStringEntities(
1698 json.substr(startString+1,i-startString-1));
1706 if(jsonPathType[jsonPathType.size()-1] !=
'{'
1709 __COUT__ <<
"Invalid ':' position" << std::endl;
1714 jsonPathType.push_back(
'K');
1715 jsonPath.push_back(extractedString);
1733 if(lastPopType ==
'{')
1736 if(jsonPathType[jsonPathType.size()-1] ==
'K')
1739 jsonPath.pop_back();
1740 jsonPathType.pop_back();
1746 currVal = extractedString;
1749 if(endNumber == (
unsigned int)-1 ||
1750 endNumber <= startNumber)
1753 if(endNumber <= startNumber)
1756 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
1759 currDepth = bracketCount;
1761 if(jsonPathType[jsonPathType.size()-1] ==
'K')
1763 currKey = jsonPath[jsonPathType.size()-1];
1768 jsonPath.pop_back();
1769 jsonPathType.pop_back();
1771 else if(jsonPathType[jsonPathType.size()-1] ==
'[')
1774 for(
unsigned int k=jsonPathType.size()-2; k<jsonPathType.size(); --k)
1775 if(jsonPathType[k] ==
'K')
1777 currKey = jsonPath[k];
1782 __COUT__ <<
"Invalid array position" << std::endl;
1791 __COUT__ <<
"Invalid ',' position" << std::endl;
1801 jsonPathType.push_back(
'{');
1802 jsonPath.push_back(
"{");
1814 if(lastPopType !=
'{' &&
1815 jsonPathType[jsonPathType.size()-1] ==
'K')
1817 currDepth = bracketCount;
1818 currKey = jsonPath[jsonPathType.size()-1];
1820 currVal = extractedString;
1823 if(endNumber == (
unsigned int)-1 ||
1824 endNumber <= startNumber)
1827 if(endNumber <= startNumber)
1830 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
1834 jsonPath.pop_back();
1835 jsonPathType.pop_back();
1838 if(jsonPathType[jsonPathType.size()-1] !=
'{')
1840 __COUT__ <<
"Invalid '}' position" << std::endl;
1844 jsonPath.pop_back();
1845 jsonPathType.pop_back();
1850 jsonPathType.push_back(
'[');
1851 jsonPath.push_back(
"[");
1859 if(jsonPathType[jsonPathType.size()-1] !=
'[')
1861 __COUT__ <<
"Invalid ']' position" << std::endl;
1865 currDepth = bracketCount;
1869 currVal = extractedString;
1872 if(endNumber == (
unsigned int)-1 ||
1873 endNumber <= startNumber)
1876 if(endNumber <= startNumber)
1879 currVal = json.substr(startNumber+1,endNumber-startNumber-1);
1884 for(
unsigned int k=jsonPathType.size()-2; k<jsonPathType.size(); --k)
1885 if(jsonPathType[k] ==
'K')
1887 currKey = jsonPath[k];
1892 __COUT__ <<
"Invalid array position" << std::endl;
1897 if(jsonPathType[jsonPathType.size()-1] !=
'[')
1899 __COUT__ <<
"Invalid ']' position" << std::endl;
1903 jsonPath.pop_back();
1904 jsonPathType.pop_back();
1912 if(startNumber != (
unsigned int)-1 &&
1913 endNumber == (
unsigned int)-1)
1922 std::cout << i <<
":\t" << json[i] <<
" - ";
1924 std::cout <<
"ExtKey=";
1925 for(
unsigned int k=0;k<jsonPath.size();++k)
1926 std::cout << jsonPath[k] <<
"/";
1928 std::cout << lastPopType <<
" ";
1929 std::cout << bracketCount <<
" ";
1930 std::cout << sqBracketCount <<
" ";
1931 std::cout << inQuotes <<
" ";
1932 std::cout << newValue <<
"-";
1933 std::cout << currKey <<
"-{" << currDepth <<
"}:" ;
1934 std::cout << currVal <<
" ";
1935 std::cout << startNumber <<
"-";
1936 std::cout << endNumber <<
" ";
1968 for(
unsigned int k=0;k<keys.size();++k)
1969 if((currDepth == 1 && keys[k] == currKey) ||
1970 (currDepth > 1 && keys[k] == jsonPath[1]))
1973 if(matchedKey != (
unsigned int)-1)
1980 case CV_JSON_FILL_NAME:
1981 if(currDepth == 1) setTableName(currVal);
1983 case CV_JSON_FILL_COMMENT:
1984 if(currDepth == 1) setComment(currVal);
1986 case CV_JSON_FILL_AUTHOR:
1987 if(currDepth == 1) setAuthor(currVal);
1989 case CV_JSON_FILL_CREATION_TIME:
1990 if(currDepth == 1) setCreationTime(strtol(currVal.c_str(),0,10));
1995 case CV_JSON_FILL_DATA_SET:
2004 unsigned int col, ccnt = 0;
2005 unsigned int noc = getNumberOfColumns();
2006 for(;ccnt<noc;++ccnt)
2012 if(fillWithLooseColumnMatching_)
2024 if(getNumberOfRows() == 1)
2025 sourceColumnNames_.emplace(currKey);
2029 if(row >= getNumberOfRows())
2031 __SS__ <<
"Invalid row" << std::endl;
2032 std::cout << ss.str();
2033 throw std::runtime_error(ss.str());
2037 theDataView_[row][col] = currVal;
2042 col = (ccnt + colSpeedup) % noc;
2048 keyIsComment =
true;
2049 for(keyIsMatchIndex=0, keyIsMatchStorageIndex=0, keyIsMatchCommentIndex=0;
2050 keyIsMatchIndex<currKey.size();++keyIsMatchIndex)
2052 if(columnsInfo_[col].getStorageName()[keyIsMatchStorageIndex] ==
'_')
2053 ++keyIsMatchStorageIndex;
2054 if(currKey[keyIsMatchIndex] ==
'_')
2058 if(keyIsMatchStorageIndex >= columnsInfo_[col].getStorageName().size() ||
2059 currKey[keyIsMatchIndex] !=
2060 columnsInfo_[col].getStorageName()[keyIsMatchStorageIndex])
2069 if(keyIsComment && keyIsMatchCommentIndex < COMMENT_ALT_KEY.size())
2071 if(currKey[keyIsMatchIndex] != COMMENT_ALT_KEY[keyIsMatchCommentIndex])
2074 keyIsComment =
false;
2078 ++keyIsMatchStorageIndex;
2081 if(keyIsMatch || keyIsComment)
2086 if(getNumberOfRows())
2087 sourceColumnMissingCount_ += getNumberOfColumns() - colFoundCount;
2095 if(getNumberOfRows() == 1)
2096 sourceColumnNames_.emplace(currKey);
2100 if(row >= getNumberOfRows())
2102 __SS__ <<
"Invalid row" << std::endl;
2103 __COUT__ <<
"\n" << ss.str();
2104 throw std::runtime_error(ss.str());
2108 theDataView_[row][col] = currVal;
2114 colSpeedup = (colSpeedup + 1) % noc;
2116 if(ccnt >= getNumberOfColumns())
2118 __SS__ <<
"\n\nInvalid column in JSON source data: " <<
2119 currKey <<
" not found in column names of table named " <<
2120 getTableName() <<
"." <<
2122 __COUT__ <<
"\n" << ss.str();
2125 ++sourceColumnMismatchCount_;
2126 if(getNumberOfRows() == 1)
2127 sourceColumnNames_.emplace(currKey);
2160 bool ConfigurationView::isURIEncodedCommentTheSame(
const std::string &comment)
const
2162 std::string compareStr = StringMacros::decodeURIComponent(comment);
2163 return comment_ == compareStr;
2218 int ConfigurationView::fillFromCSV(
const std::string &data,
const int &dataOffset,
2219 const std::string &author)
2220 throw(std::runtime_error)
2226 int j = data.find(
',',i);
2227 int k = data.find(
';',i);
2229 bool rowWasModified;
2230 unsigned int countRowsModified = 0;
2231 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
2232 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
2235 while(k != (
int)(std::string::npos))
2237 rowWasModified =
false;
2238 if(r >= (
int)getNumberOfRows())
2242 rowWasModified =
true;
2245 while(j < k && j != (
int)(std::string::npos))
2250 if(c >= (
int)getNumberOfColumns()-2)
2253 j = data.find(
',',i);
2258 if(setURIEncodedValue(data.substr(i,j-i),r,c))
2259 rowWasModified =
true;
2262 j = data.find(
',',i);
2267 if(author !=
"" && rowWasModified)
2269 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << std::endl;
2270 setValue(author,r,authorCol);
2271 setValue(time(0),r,timestampCol);
2274 if(rowWasModified) ++countRowsModified;
2281 j = data.find(
',',i);
2282 k = data.find(
';',i);
2286 while(r < (
int)getNumberOfRows())
2289 __COUT__ <<
"Row deleted: " << (int)r << std::endl;
2290 ++countRowsModified;
2293 __COUT_INFO__ <<
"countRowsModified=" <<
2294 countRowsModified << std::endl;
2296 if(!countRowsModified)
2298 __SS__ <<
"No rows were modified! No reason to fill a view with same content." << std::endl;
2299 __COUT__ <<
"\n" << ss.str();
2306 sourceColumnNames_.clear();
2307 for(
unsigned int i=0;i<getNumberOfColumns();++i)
2308 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
2328 bool ConfigurationView::setURIEncodedValue(
const std::string &value,
const unsigned int &r,
2329 const unsigned int &c,
const std::string &author)
2331 if(!(c < columnsInfo_.size() && r < getNumberOfRows()))
2333 __SS__ <<
"Invalid row (" << (int)r <<
") col (" << (
int)c << ") requested!" <<
2334 "Number of Rows = " << getNumberOfRows() <<
2335 "Number of Columns = " << columnsInfo_.size() << std::endl;
2337 throw std::runtime_error(ss.str());
2340 std::
string valueStr =
StringMacros::decodeURIComponent(value);
2341 std::
string originalValueStr = getValueAsString(r,c,false);
2347 if(columnsInfo_[c].getDataType() ==
ViewColumnInfo::DATATYPE_NUMBER)
2350 std::string convertedString = StringMacros::convertEnvironmentVariables(valueStr);
2351 if(!StringMacros::isNumber(convertedString))
2353 __SS__ <<
"\tIn configuration " << tableName_
2354 <<
" at column=" << columnsInfo_[c].getName()
2355 <<
" the value set (" << convertedString <<
")"
2356 <<
" is not a number! Please fix it or change the column type..." << std::endl;
2357 throw std::runtime_error(ss.str());
2359 theDataView_[r][c] = valueStr;
2361 else if(columnsInfo_[c].getDataType() == ViewColumnInfo::DATATYPE_TIME)
2373 setValue(time_t(strtol(valueStr.c_str(),0,10)),
2377 theDataView_[r][c] = valueStr;
2379 bool rowWasModified = (originalValueStr != getValueAsString(r,c,
false));
2382 if(author !=
"" && rowWasModified)
2384 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << std::endl;
2385 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
2386 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
2387 setValue(author,r,authorCol);
2388 setValue(time(0),r,timestampCol);
2391 return rowWasModified;
2395 void ConfigurationView::resizeDataView(
unsigned int nRows,
unsigned int nCols)
2398 theDataView_.resize(nRows, std::vector<std::string>(nCols));
2408 int ConfigurationView::addRow(
const std::string &author,
2409 bool incrementUniqueData,
2410 std::string baseNameAutoUID)
2412 int row = getNumberOfRows();
2413 theDataView_.resize(getNumberOfRows()+1,std::vector<std::string>(getNumberOfColumns()));
2415 std::vector<std::string> defaultRowValues =
2416 getDefaultRowValues();
2418 char indexString[1000];
2419 std::string tmpString, baseString;
2422 unsigned int maxUniqueData;
2423 std::string numString;
2427 for(
unsigned int col=0;col<getNumberOfColumns();++col)
2434 if(incrementUniqueData &&
2435 (col == getColUID() || (row && columnsInfo_[col].getType() ==
2436 ViewColumnInfo::TYPE_UNIQUE_DATA)))
2449 for(
unsigned int r=0;r<getNumberOfRows()-1;++r)
2454 tmpString = theDataView_[r][col];
2458 for(index = tmpString.length()-1;index < tmpString.length(); --index)
2461 if(!(tmpString[index] >=
'0' && tmpString[index] <=
'9'))
break;
2467 if(tmpString.length() &&
2471 numString = tmpString.substr(index+1);
2472 tmpString = tmpString.substr(0,index+1);
2479 sscanf(numString.c_str(),
"%u",&index);
2481 if(index > maxUniqueData)
2483 maxUniqueData = index;
2484 baseString = tmpString;
2491 sprintf(indexString,
"%u",maxUniqueData);
2495 if(col == getColUID())
2498 if(baseNameAutoUID !=
"")
2499 theDataView_[row][col] = baseNameAutoUID + indexString;
2501 theDataView_[row][col] = baseString + indexString;
2504 theDataView_[row][col] = baseString + indexString;
2506 __COUT__ <<
"New unique data entry is '" << theDataView_[row][col] <<
"'" << __E__;
2511 theDataView_[row][col] = defaultRowValues[col];
2516 __COUT__ <<
"Row=" << row <<
" was created!" << std::endl;
2517 int authorCol = findColByType(ViewColumnInfo::TYPE_AUTHOR);
2518 int timestampCol = findColByType(ViewColumnInfo::TYPE_TIMESTAMP);
2519 setValue(author,row,authorCol);
2520 setValue(time(0),row,timestampCol);
2550 void ConfigurationView::deleteRow(
int r)
2552 if(r >= (
int)getNumberOfRows())
2555 __SS__ <<
"Row " << (int)r <<
" is out of bounds (Row Count = " <<
2556 getNumberOfRows() <<
") and can not be deleted." <<
2558 throw std::runtime_error(ss.str());
2561 theDataView_.erase(theDataView_.begin()+r);
2578 const bool ConfigurationView::getChildLink(
const unsigned int& c,
bool& isGroup,
2579 std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>& linkPair)
const
2582 if(!(c < columnsInfo_.size()))
2584 __SS__ <<
"Invalid col (" << (int)c <<
") requested!" << std::endl;
2585 throw std::runtime_error(ss.str());
2592 if((isGroup = columnsInfo_[c].isChildLinkGroupID()) ||
2593 columnsInfo_[c].isChildLinkUID())
2597 linkPair.second = c;
2598 std::string index = columnsInfo_[c].getChildLinkIndex();
2603 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
2606 if(col == c)
continue;
2607 else if(columnsInfo_[col].isChildLink() &&
2608 index == columnsInfo_[col].getChildLinkIndex())
2612 linkPair.first = col;
2618 __SS__ <<
"\tIn view: " << tableName_ <<
2619 ", Can't find complete child link for column name " << columnsInfo_[c].getName() << std::endl;
2620 throw std::runtime_error(ss.str());
2623 if(!columnsInfo_[c].isChildLink())
2628 std::string index = columnsInfo_[c].getChildLinkIndex();
2633 for(
unsigned int col=0; col<columnsInfo_.size(); ++col)
2636 if(col == c)
continue;
2648 if(((columnsInfo_[col].isChildLinkUID() && !(isGroup =
false)) ||
2649 (columnsInfo_[col].isChildLinkGroupID() && (isGroup =
true)))
2650 && index == columnsInfo_[col].getChildLinkIndex())
2654 linkPair.second = col;
2660 __SS__ <<
"\tIn view: " << tableName_ <<
2661 ", Can't find complete child link id for column name " << columnsInfo_[c].getName() << std::endl;
2662 throw std::runtime_error(ss.str());