1 #include "otsdaq/TableCore/TableView.h"
2 #include "otsdaq/Macros/StringMacros.h"
3 #include "otsdaq/TableCore/TableBase.h"
13 #define __MF_SUBJECT__ "TableView"
15 #define __COUT_HDR__ (tableName_ + "v" + version_.toString() + "\t<> ")
17 const unsigned int TableView::INVALID = -1;
21 : storageData_(tableName)
22 , tableName_(
TableBase::convertToCaps(storageData_))
26 , creationTime_(time(0))
30 , colPriority_(INVALID)
31 , fillWithLooseColumnMatching_(false)
32 , getSourceRawData_(false)
33 , sourceColumnMismatchCount_(0)
34 , sourceColumnMissingCount_(0)
40 __SS__ <<
"Do not allow anonymous table view construction!" << __E__;
48 TableView::~TableView(
void) {}
56 __SS__ <<
"Invalid use of operator=... Should not directly copy a TableView. Please "
57 "use TableView::copy(sourceView,author,comment)";
60 __COUT__ << ss.str() << __E__;
68 const std::string& author)
71 version_ = destinationVersion;
72 comment_ = src.comment_;
75 lastAccessTime_ = time(0);
80 for(
auto& c : src.columnsInfo_)
81 columnsInfo_.push_back(c);
83 theDataView_ = src.theDataView_;
84 sourceColumnNames_ = src.sourceColumnNames_;
90 std::string tmpCachePrepend = TableBase::GROUP_CACHE_PREPEND;
92 std::string tmpJsonDocPrepend = TableBase::JSON_DOC_PREPEND;
96 if(tableName_.substr(0, tmpCachePrepend.length()) == tmpCachePrepend ||
97 tableName_.substr(0, tmpJsonDocPrepend.length()) == tmpJsonDocPrepend)
99 __COUTT__ <<
"TableView copy for '" << tableName_ <<
"' done." << __E__;
128 unsigned int srcOffsetRow ,
129 unsigned int srcRowsToCopy ,
130 unsigned int destOffsetRow ,
131 unsigned char generateUniqueDataColumns ,
132 const std::string& baseNameAutoUID )
134 __COUTTV__(destOffsetRow);
135 __COUTTV__(srcOffsetRow);
136 __COUTTV__(srcRowsToCopy);
138 unsigned int retRow = (
unsigned int)-1;
141 if(src.getNumberOfColumns() != getNumberOfColumns())
143 __SS__ <<
"Error! Number of Columns of source view must match destination view."
144 <<
"Dimension of source is [" << src.getNumberOfColumns()
145 <<
"] and of destination is [" << getNumberOfColumns() <<
"]." << __E__;
149 unsigned int srcRows = src.getNumberOfRows();
151 for(
unsigned int r = 0; r < srcRowsToCopy; ++r)
153 if(r + srcOffsetRow >= srcRows)
156 destOffsetRow =
addRow(author,
157 generateUniqueDataColumns ,
161 if(retRow == (
unsigned int)-1)
162 retRow = destOffsetRow;
165 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
166 if(generateUniqueDataColumns &&
168 columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_DATA ||
169 columnsInfo_[col].getType() ==
170 TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA))
174 __COUTT__ <<
"Copying [" << r + srcOffsetRow <<
"][" << col <<
"] to ["
175 << destOffsetRow <<
"][" << col
176 <<
"] = " << src.theDataView_[r + srcOffsetRow][col] << __E__;
177 theDataView_[destOffsetRow][col] =
178 src.theDataView_[r + srcOffsetRow][col];
203 std::set<std::string> colNameSet;
204 std::string capsColName, colName;
205 for(
auto& colInfo : columnsInfo_)
207 colName = colInfo.getStorageName();
208 if(colName ==
"COMMENT_DESCRIPTION")
211 for(
unsigned int i = 0; i < colName.size(); ++i)
213 if(colName[i] ==
'_')
215 capsColName += colName[i];
218 colNameSet.emplace(capsColName);
221 if(colNameSet.size() != columnsInfo_.size())
223 __SS__ <<
"Table Error:\t"
224 <<
" Columns names must be unique! There are " << columnsInfo_.size()
225 <<
" columns and the unique name count is " << colNameSet.size()
247 if(sourceColumnNames_.size() == 0)
248 for(
unsigned int i = 0; i < getNumberOfColumns(); ++i)
249 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
253 if((colPos =
findColByType(TableViewColumnInfo::TYPE_COMMENT)) != INVALID)
255 if(columnsInfo_[colPos].getName() != TableViewColumnInfo::COL_NAME_COMMENT)
257 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
258 <<
" data type column must have name="
259 << TableViewColumnInfo::COL_NAME_COMMENT << __E__;
263 if(
findColByType(TableViewColumnInfo::TYPE_COMMENT, colPos + 1) !=
266 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
267 <<
" data type in column " << columnsInfo_[colPos].getName()
268 <<
" is repeated. This is not allowed." << __E__;
272 if(colPos != getNumberOfColumns() - 3)
274 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
275 <<
" data type column must be 3rd to last (in column "
276 << getNumberOfColumns() - 3 <<
")." << __E__;
282 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
283 <<
" data type column "
284 <<
" is missing. This is not allowed." << __E__;
289 if((colPos =
findColByType(TableViewColumnInfo::TYPE_AUTHOR)) != INVALID)
291 if(
findColByType(TableViewColumnInfo::TYPE_AUTHOR, colPos + 1) !=
294 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR
295 <<
" data type in column " << columnsInfo_[colPos].getName()
296 <<
" is repeated. This is not allowed." << __E__;
300 if(colPos != getNumberOfColumns() - 2)
302 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR
303 <<
" data type column must be 2nd to last (in column "
304 << getNumberOfColumns() - 2 <<
")." << __E__;
310 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR
311 <<
" data type column "
312 <<
" is missing. This is not allowed." << __E__;
317 if((colPos =
findColByType(TableViewColumnInfo::TYPE_TIMESTAMP)) != INVALID)
319 if(
findColByType(TableViewColumnInfo::TYPE_TIMESTAMP, colPos + 1) !=
322 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP
323 <<
" data type in column " << columnsInfo_[colPos].getName()
324 <<
" is repeated. This is not allowed." << __E__;
328 if(colPos != getNumberOfColumns() - 1)
330 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP
331 <<
" data type column must be last (in column "
332 << getNumberOfColumns() - 1 <<
")." << __E__;
333 __COUT_ERR__ <<
"\n" << ss.str();
339 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP
340 <<
" data type column "
341 <<
" is missing. This is not allowed." << __E__;
348 std::set<std::string > uidSet;
349 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
351 if(uidSet.find(theDataView_[row][colUID_]) != uidSet.end())
353 __SS__ << (
"Entries in UID are not unique. Specifically at row=" +
354 std::to_string(row) +
" value=" + theDataView_[row][colUID_])
359 if(theDataView_[row][colUID_].size() == 0)
361 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' "
362 <<
" was identified. UIDs must contain at least 1 character."
367 for(
unsigned int i = 0; i < theDataView_[row][colUID_].size(); ++i)
368 if(!((theDataView_[row][colUID_][i] >=
'A' &&
369 theDataView_[row][colUID_][i] <=
'Z') ||
370 (theDataView_[row][colUID_][i] >=
'a' &&
371 theDataView_[row][colUID_][i] <=
'z') ||
372 (theDataView_[row][colUID_][i] >=
'0' &&
373 theDataView_[row][colUID_][i] <=
'9') ||
374 (theDataView_[row][colUID_][i] ==
'-' ||
375 theDataView_[row][colUID_][i] ==
'_')))
377 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' "
378 <<
" was identified. UIDs must contain only letters, numbers, "
379 <<
"dashes, and underscores." << __E__;
383 uidSet.insert(theDataView_[row][colUID_]);
385 if(uidSet.size() != getNumberOfRows())
387 __SS__ <<
"Entries in UID are not unique!"
388 <<
"There are " << getNumberOfRows()
389 <<
" records and the unique UID count is " << uidSet.size() << __E__;
394 colPos = (
unsigned int)-1;
395 while((colPos =
findColByType(TableViewColumnInfo::TYPE_UNIQUE_DATA,
396 colPos + 1)) != INVALID)
398 std::set<std::string > uDataSet;
399 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
401 if(uDataSet.find(theDataView_[row][colPos]) != uDataSet.end())
403 __SS__ <<
"Entries in Unique Data column "
404 << columnsInfo_[colPos].getName()
405 << (
" are not unique. Specifically at row=" +
406 std::to_string(row) +
407 " value=" + theDataView_[row][colPos])
411 uDataSet.insert(theDataView_[row][colPos]);
413 if(uDataSet.size() != getNumberOfRows())
415 __SS__ <<
"Entries in Unique Data column "
416 << columnsInfo_[colPos].getName() <<
" are not unique!"
417 <<
"There are " << getNumberOfRows()
418 <<
" records and the unique data count is " << uDataSet.size()
426 colPos = (
unsigned int)-1;
427 while((colPos =
findColByType(TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA,
428 colPos + 1)) != INVALID)
433 for(
unsigned int groupIdColPos = 0; groupIdColPos < columnsInfo_.size();
435 if(columnsInfo_[groupIdColPos].isGroupID())
437 std::map<std::string ,
438 std::pair<
unsigned int ,
439 std::set<std::string >>>
442 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
446 for(
const auto& groupId : groupIds)
448 uGroupDataSets[groupId].first++;
450 if(uGroupDataSets[groupId].second.find(
451 theDataView_[row][colPos]) !=
452 uGroupDataSets[groupId].second.end())
454 __SS__ <<
"Entries in Unique Group Data column " << colPos
455 <<
":" << columnsInfo_[colPos].getName()
456 <<
" are not unique for group ID '" << groupId
457 <<
".' Specifically at row=" << std::to_string(row)
458 <<
" value=" << theDataView_[row][colPos] << __E__;
461 uGroupDataSets[groupId].second.insert(
462 theDataView_[row][colPos]);
466 for(
const auto& groupPair : uGroupDataSets)
467 if(uGroupDataSets[groupPair.first].second.size() !=
468 uGroupDataSets[groupPair.first].first)
471 <<
"Entries in Unique Data column "
472 << columnsInfo_[colPos].getName()
473 <<
" are not unique for group '" << groupPair.first
475 <<
"There are " << uGroupDataSets[groupPair.first].first
476 <<
" records and the unique data count is "
477 << uGroupDataSets[groupPair.first].second.size() << __E__;
483 auto rowDefaults = initRowDefaults();
490 std::set<std::string> groupIdIndexes, childLinkIndexes, childLinkIdLabels;
491 unsigned int groupIdIndexesCount = 0, childLinkIndexesCount = 0,
492 childLinkIdLabelsCount = 0;
494 std::pair<
unsigned int ,
unsigned int > tmpLinkPair;
497 if(getNumberOfRows() != theDataView_.size())
499 __SS__ <<
"Impossible row mismatch " << getNumberOfRows() <<
" vs "
500 << theDataView_.size() <<
"! How did you get here?" << __E__;
503 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
504 if(getNumberOfColumns() != theDataView_[row].size())
506 __SS__ <<
"Impossible col mismatch " << getNumberOfColumns() <<
" vs ["
507 << row <<
"]" << theDataView_[row].size()
508 <<
"! How did you get here?" << __E__;
511 if(getNumberOfColumns() != columnsInfo_.size())
513 __SS__ <<
"Impossible col info mismatch " << getNumberOfColumns() <<
" vs "
514 << columnsInfo_.size() <<
"! How did you get here?" << __E__;
517 if(getNumberOfColumns() != rowDefaults.size())
519 __SS__ <<
"Impossible col default mismatch " << getNumberOfColumns() <<
" vs "
520 << rowDefaults.size() <<
"! How did you get here?" << __E__;
524 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
526 if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
528 const std::vector<std::string>& theDataChoices =
529 columnsInfo_[col].getDataChoices();
532 if(theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=1")
536 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
540 if(theDataView_[row][col] == rowDefaults[col])
543 for(
const auto& choice : theDataChoices)
545 if(theDataView_[row][col] == choice)
553 __SS__ << getTableName() <<
" Error:\t'" << theDataView_[row][col]
554 <<
"' in column " << columnsInfo_[col].getName()
555 <<
" is not a valid Fixed Choice option. "
556 <<
"Possible values are as follows: ";
558 ss << columnsInfo_[col].getDefaultValue()
559 << (columnsInfo_[col].getDataChoices().size() ?
", " :
"");
560 for(
unsigned int i = 0;
561 i < columnsInfo_[col].getDataChoices().size();
564 if(columnsInfo_[col].getDataChoices()[i] ==
"arbitraryBool=0")
567 if(i && (i != 1 || columnsInfo_[col].getDataChoices()[0] !=
570 ss << columnsInfo_[col].getDataChoices()[i];
577 else if(columnsInfo_[col].isChildLink())
581 const std::vector<std::string>& theDataChoices =
582 columnsInfo_[col].getDataChoices();
585 if(!theDataChoices.size() || theDataChoices[0] ==
"arbitraryBool=1")
590 (theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=0");
594 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
599 for(
const auto& choice : theDataChoices)
601 if(skipOne && !hasSkipped)
607 if(theDataView_[row][col] == choice)
615 __SS__ << getTableName() <<
" Error:\t the value '"
616 << theDataView_[row][col] <<
"' in column "
617 << columnsInfo_[col].getName()
618 <<
" is not a valid Fixed Choice option. "
619 <<
"Possible values are as follows: ";
624 for(
unsigned int i = skipOne ? 1 : 0;
625 i < columnsInfo_[col].getDataChoices().size();
628 if(i > (skipOne ? 1 : 0))
630 ss << columnsInfo_[col].getDataChoices()[i];
637 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_ON_OFF)
638 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
640 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" ||
641 theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
642 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_ON;
643 else if(theDataView_[row][col] ==
"0" ||
644 theDataView_[row][col] ==
"off" ||
645 theDataView_[row][col] ==
"Off" ||
646 theDataView_[row][col] ==
"OFF")
647 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_OFF;
650 __SS__ << getTableName() <<
" Error:\t the value '"
651 << theDataView_[row][col] <<
"' in column "
652 << columnsInfo_[col].getName()
653 <<
" is not a valid Type (On/Off) std::string. Possible "
654 "values are 1, on, On, ON, 0, off, Off, OFF."
659 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_TRUE_FALSE)
660 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
662 if(theDataView_[row][col] ==
"1" ||
663 theDataView_[row][col] ==
"true" ||
664 theDataView_[row][col] ==
"True" ||
665 theDataView_[row][col] ==
"TRUE")
666 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_TRUE;
667 else if(theDataView_[row][col] ==
"0" ||
668 theDataView_[row][col] ==
"false" ||
669 theDataView_[row][col] ==
"False" ||
670 theDataView_[row][col] ==
"FALSE")
671 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_FALSE;
674 __SS__ << getTableName() <<
" Error:\t the value '"
675 << theDataView_[row][col] <<
"' in column "
676 << columnsInfo_[col].getName()
677 <<
" is not a valid Type (True/False) std::string. "
678 "Possible values are 1, true, True, TRUE, 0, false, "
684 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_YES_NO)
685 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
687 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" ||
688 theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
689 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_YES;
690 else if(theDataView_[row][col] ==
"0" ||
691 theDataView_[row][col] ==
"no" ||
692 theDataView_[row][col] ==
"No" ||
693 theDataView_[row][col] ==
"NO")
694 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_NO;
697 __SS__ << getTableName() <<
" Error:\t the value '"
698 << theDataView_[row][col] <<
"' in column "
699 << columnsInfo_[col].getName()
700 <<
" is not a valid Type (Yes/No) std::string. Possible "
701 "values are 1, yes, Yes, YES, 0, no, No, NO."
706 else if(columnsInfo_[col].isGroupID())
708 colLinkGroupIDs_[columnsInfo_[col].getChildLinkIndex()] =
711 groupIdIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
712 ++groupIdIndexesCount;
714 else if(columnsInfo_[col].isChildLink())
717 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
718 if(theDataView_[row][col] ==
"NoLink" ||
719 theDataView_[row][col] ==
"No_Link" ||
720 theDataView_[row][col] ==
"NOLINK" ||
721 theDataView_[row][col] ==
"NO_LINK" ||
722 theDataView_[row][col] ==
"Nolink" ||
723 theDataView_[row][col] ==
"nolink" ||
724 theDataView_[row][col] ==
"noLink")
725 theDataView_[row][col] =
726 TableViewColumnInfo::DATATYPE_LINK_DEFAULT;
729 childLinkIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
730 ++childLinkIndexesCount;
733 if(columnsInfo_[col].getDataType() !=
734 TableViewColumnInfo::DATATYPE_STRING)
736 __SS__ << getTableName() <<
" Error:\t"
737 <<
"Column " << col <<
" with name '"
738 << columnsInfo_[col].getName()
739 <<
"' is a Child Link column and has an illegal data type of '"
740 << columnsInfo_[col].getDataType()
741 <<
"'. The data type for Child Link columns must be "
742 << TableViewColumnInfo::DATATYPE_STRING << __E__;
749 else if(columnsInfo_[col].isChildLinkUID() ||
750 columnsInfo_[col].isChildLinkGroupID())
753 childLinkIdLabels.emplace(columnsInfo_[col].getChildLinkIndex());
754 ++childLinkIdLabelsCount;
757 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
758 if(theDataView_[row][col] ==
"")
759 theDataView_[row][col] = rowDefaults[col];
766 if(columnsInfo_[col].isNumberDataType())
768 std::string minimumValueString = columnsInfo_[col].getMinValue();
769 std::string maximumValueString = columnsInfo_[col].getMaxValue();
770 double minimumValue, maximumValue, valueFromTable;
771 bool minExists =
false, maxExists =
false;
773 if(!minimumValueString.empty())
780 __SS__ <<
"Inavlid user spec'd min value '" << minimumValueString
781 <<
"' which is not a valid number. The minimum value must "
782 "be a number (environment variables and math "
783 "operations are allowed)."
789 if(!maximumValueString.empty())
796 __SS__ <<
"Inavlid user spec'd max value '" << maximumValueString
797 <<
"' which is not a valid number. The maximum value must "
798 "be a number (environment variables and math "
799 "operations are allowed)."
805 if(minExists && maxExists && minimumValue > maximumValue)
807 __SS__ <<
"Minimum value is greater than maximum, check table editor "
813 if(minExists || maxExists)
814 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
817 if(minExists && valueFromTable < minimumValue)
820 <<
"The value '" << valueFromTable <<
"'("
823 <<
") at [row,col]=[" << row <<
"," << col
824 <<
"] is outside the established limits: "
826 <<
" is lower than the specified minimum " << minimumValue
830 if(maxExists && valueFromTable > maximumValue)
833 <<
"This value '" << valueFromTable <<
"'("
836 <<
") at [row,col]=[" << row <<
"," << col
837 <<
"] is outside the established limits: "
839 <<
" is greater than the specified maximum "
840 << maximumValue <<
"." << __E__;
848 if(groupIdIndexes.size() != groupIdIndexesCount)
850 __SS__ << (
"GroupId Labels are not unique!") <<
"There are "
851 << groupIdIndexesCount <<
" GroupId Labels and the unique count is "
852 << groupIdIndexes.size() << __E__;
855 if(childLinkIndexes.size() != childLinkIndexesCount)
857 __SS__ << (
"Child Link Labels are not unique!") <<
"There are "
858 << childLinkIndexesCount
859 <<
" Child Link Labels and the unique count is "
860 << childLinkIndexes.size() << __E__;
863 if(childLinkIdLabels.size() != childLinkIdLabelsCount)
865 __SS__ << (
"Child Link ID Labels are not unique!") <<
"There are "
866 << childLinkIdLabelsCount
867 <<
" Child Link ID Labels and the unique count is "
868 << childLinkIdLabels.size() << __E__;
874 __COUT__ <<
"Error occured in TableView::init() for version=" << version_
888 bool doConvertEnvironmentVariables)
const
890 if(!(row < getNumberOfRows() && col < theDataView_[row].size()))
892 __SS__ <<
"Invalid row col requested " << row <<
"," << col <<
" vs "
893 << getNumberOfRows() <<
"," << columnsInfo_.size() <<
"/"
894 << theDataView_[row].size() << __E__;
899 theDataView_[row][col], col, doConvertEnvironmentVariables);
909 bool doConvertEnvironmentVariables)
const
911 if(col >= columnsInfo_.size())
913 __SS__ <<
"Invalid col requested" << __E__;
917 if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA &&
919 value == columnsInfo_[col].getDefaultDefaultValue(columnsInfo_[col].getType(),
920 columnsInfo_[col].getDataType()))
924 std::vector<std::string> choices = columnsInfo_[col].getDataChoices();
927 bool skipOne = (choices.size() && choices[0].find(
"arbitraryBool=") == 0);
928 size_t index = (skipOne ? 1 : 0);
929 if(choices.size() > index)
931 return doConvertEnvironmentVariables
937 if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_STRING)
938 return doConvertEnvironmentVariables
941 else if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
944 doConvertEnvironmentVariables
950 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
951 <<
" in configuration " << tableName_
952 <<
" at column=" << columnsInfo_[col].getName()
953 <<
" for getValue with type '"
968 bool doConvertEnvironmentVariables)
const
970 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
972 __SS__ << (
"Invalid row col requested") << __E__;
976 __COUTS__(30) << columnsInfo_[col].getType() <<
" " << col << __E__;
978 if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_ON_OFF)
980 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" ||
981 theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
982 return TableViewColumnInfo::TYPE_VALUE_ON;
984 return TableViewColumnInfo::TYPE_VALUE_OFF;
986 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_TRUE_FALSE)
988 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" ||
989 theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
990 return TableViewColumnInfo::TYPE_VALUE_TRUE;
992 return TableViewColumnInfo::TYPE_VALUE_FALSE;
994 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_YES_NO)
996 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" ||
997 theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
998 return TableViewColumnInfo::TYPE_VALUE_YES;
1000 return TableViewColumnInfo::TYPE_VALUE_NO;
1003 return doConvertEnvironmentVariables
1005 : theDataView_[row][col];
1018 bool doConvertEnvironmentVariables ,
1019 bool quotesToDoubleQuotes )
const
1021 std::string val =
getValueAsString(row, col, doConvertEnvironmentVariables);
1022 std::string retVal =
"";
1023 retVal.reserve(val.size());
1024 for(
unsigned int i = 0; i < val.size(); ++i)
1028 else if(val[i] ==
'\t')
1030 else if(val[i] ==
'\r')
1037 if(quotesToDoubleQuotes && val[i] ==
'"')
1039 else if(!quotesToDoubleQuotes && val[i] ==
'"')
1052 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
1054 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
1058 if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_STRING)
1059 theDataView_[row][col] = value;
1063 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
1064 <<
" in configuration " << tableName_
1065 <<
" at column=" << columnsInfo_[col].getName()
1066 <<
" for setValue with type '"
1075 setValue(std::string(value), row, col);
1085 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
1087 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
1091 theDataView_[row][col] = value;
1104 std::string baseValueAsString ,
1105 bool doMathAppendStrategy ,
1106 std::string childLinkIndex ,
1107 std::string groupId )
1109 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
1111 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
1115 bool isUniqueGroupCol =
1116 (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA);
1117 unsigned int childLinkIndexCol = -1;
1118 if(isUniqueGroupCol)
1120 __COUTVS__(12, childLinkIndex);
1121 __COUTVS__(12, groupId);
1123 __COUTVS__(12, childLinkIndexCol);
1126 __COUTT__ <<
"Current '" << columnsInfo_[col].getName() <<
"' "
1127 << (isUniqueGroupCol ?
"(Unique in Group) " :
"")
1128 <<
"unique data entry is data[" << row <<
"][" << col <<
"] = '"
1129 << theDataView_[row][col] <<
"' baseValueAsString = " << baseValueAsString
1130 <<
" doMathAppendStrategy = " << doMathAppendStrategy << __E__;
1132 bool firstConflict =
true;
1133 int maxUniqueData = -1;
1134 std::string tmpString =
"";
1137 std::string numString;
1138 std::string opString;
1144 for(
unsigned int r = 0; r < getNumberOfRows(); ++r)
1149 if(isUniqueGroupCol && !isEntryInGroupCol(r, childLinkIndexCol, groupId))
1155 tmpString = theDataView_[r][col];
1157 __COUTS__(3) <<
"row[" << r <<
"] tmpString " << tmpString << __E__;
1159 for(index = tmpString.length() - 1; index < tmpString.length(); --index)
1161 __COUTS__(3) << index <<
" tmpString[index] " << tmpString[index] << __E__;
1162 if(!(tmpString[index] >=
'0' && tmpString[index] <=
'9'))
1167 __COUTS__(3) <<
"index " << index <<
" foundAny " << foundAny << __E__;
1169 if(tmpString.length() && foundAny)
1172 numString = tmpString.substr(index + 1);
1175 tmpString = tmpString.substr(0, index + 1);
1177 if(doMathAppendStrategy && tmpString.size())
1181 for(index = tmpString.length() - 1; index < tmpString.length(); --index)
1184 << index <<
" tmpString[index] " << tmpString[index] << __E__;
1185 if(!(tmpString[index] ==
'+' || tmpString[index] ==
' '))
1193 opString = tmpString.substr(index + 1);
1196 tmpString = tmpString.substr(0, index + 1);
1200 __COUTS__(3) << tmpString <<
" vs " << baseValueAsString << __E__;
1202 if(baseValueAsString !=
"" && tmpString != baseValueAsString)
1205 __COUTS__(3) <<
"Found unique data base string '" << tmpString
1206 <<
"' and number string '" << numString <<
"' in last record '"
1207 << theDataView_[r][col] <<
"'" << __E__;
1212 if(baseValueAsString.size() &&
1213 baseValueAsString[baseValueAsString.size() - 1] >=
'0' &&
1214 baseValueAsString[baseValueAsString.size() - 1] <=
'9')
1215 baseValueAsString +=
'_';
1217 firstConflict =
false;
1221 sscanf(numString.c_str(),
"%u", &index);
1223 if((
int)index > maxUniqueData)
1225 maxUniqueData = (int)index;
1227 if(baseValueAsString ==
"")
1228 baseValueAsString = tmpString;
1231 else if(maxUniqueData < 0 &&
1232 (baseValueAsString ==
"" || tmpString == baseValueAsString))
1237 if(baseValueAsString.size() &&
1238 baseValueAsString[baseValueAsString.size() - 1] >=
'0' &&
1239 baseValueAsString[baseValueAsString.size() - 1] <=
'9')
1240 baseValueAsString +=
'_';
1242 firstConflict =
false;
1249 __COUTVS__(12, maxUniqueData);
1250 __COUTVS__(12, baseValueAsString);
1252 if(maxUniqueData == -1)
1254 if(baseValueAsString !=
"")
1255 theDataView_[row][col] = baseValueAsString;
1257 theDataView_[row][col] = columnsInfo_[col].getDefaultValue();
1263 char indexString[1000];
1264 sprintf(indexString,
"%u", maxUniqueData);
1266 __COUTVS__(12, indexString);
1267 __COUTVS__(12, baseValueAsString);
1269 if(doMathAppendStrategy)
1270 theDataView_[row][col] = baseValueAsString +
" + " + indexString;
1272 theDataView_[row][col] = baseValueAsString + indexString;
1275 __COUTT__ <<
"New unique data entry is data[" << row <<
"][" << col <<
"] = '"
1276 << theDataView_[row][col] <<
"'" << __E__;
1280 std::stringstream ss;
1282 __COUT_MULTI__(13, ss.str());
1285 return theDataView_[row][col];
1291 unsigned int TableView::initColUID(
void)
1293 if(colUID_ != INVALID)
1298 if(colUID_ == INVALID)
1300 __COUT__ <<
"Column Types: " << __E__;
1301 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1302 std::cout << columnsInfo_[col].getType() <<
"() "
1303 << columnsInfo_[col].getName() << __E__;
1304 __SS__ <<
"\tMissing UID Column in table named '" << tableName_ <<
"'" << __E__;
1315 if(colUID_ != INVALID)
1318 __COUT__ <<
"Column Types: " << __E__;
1319 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1320 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1323 __SS__ << (
"Missing UID Column in config named " + tableName_ +
1324 ". (Possibly TableView was just not initialized?" +
1325 " This is the const call so can not alter class members)")
1336 unsigned int TableView::initColStatus(
void)
1338 if(colStatus_ != INVALID)
1342 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1343 if(columnsInfo_[col].getName() == TableViewColumnInfo::COL_NAME_STATUS)
1348 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1349 if(columnsInfo_[col].getName() == TableViewColumnInfo::COL_NAME_ENABLED)
1357 __SS__ <<
"\tMissing column named '" << TableViewColumnInfo::COL_NAME_STATUS
1358 <<
"' or '" << TableViewColumnInfo::COL_NAME_ENABLED <<
"' in table '"
1359 << tableName_ <<
".'" << __E__;
1360 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1361 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1362 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1372 unsigned int TableView::initColPriority(
void)
1374 if(colPriority_ != INVALID)
1375 return colPriority_;
1379 findCol(
"*" + TableViewColumnInfo::COL_NAME_PRIORITY);
1380 if(colPriority_ == INVALID)
1382 __SS__ <<
"\tMissing column named '" << TableViewColumnInfo::COL_NAME_PRIORITY
1383 <<
"' in table '" << tableName_ <<
".'" << __E__;
1384 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1385 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1386 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1391 return colPriority_;
1400 if(colStatus_ != INVALID)
1403 __SS__ <<
"\tMissing column named '" << TableViewColumnInfo::COL_NAME_STATUS
1404 <<
"' or '" << TableViewColumnInfo::COL_NAME_ENABLED <<
"' in table '"
1405 << tableName_ <<
".'"
1406 <<
" (The Status column is identified when the TableView is initialized)"
1409 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1410 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1411 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1418 __COUT_WARN__ << ss.str();
1431 if(colPriority_ != INVALID)
1432 return colPriority_;
1434 __SS__ <<
"Priority column was not found... \nColumn Types: " << __E__;
1436 ss <<
"Missing " << TableViewColumnInfo::COL_NAME_PRIORITY
1437 <<
" Column in table named '" << tableName_
1438 <<
".' (The Priority column is identified when the TableView is initialized)"
1442 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1443 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1444 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1457 const unsigned int& col,
1458 const std::string& groupID)
1461 if(isEntryInGroupCol(row, col, groupID))
1463 __SS__ <<
"GroupID (" << groupID <<
") added to row (" << row
1464 <<
" is already present!" << __E__;
1473 if(getDataView()[row][col] ==
"" ||
1474 getDataView()[row][col] == getDefaultRowValues()[col])
1477 setValue(groupID +
" | " + getDataView()[row][col], row, col);
1489 const unsigned int groupIdCol,
1490 const std::string& groupID,
1491 bool onlyStatusTrue ,
1492 bool orderedByPriority )
const
1494 std::vector<
unsigned int > retVector;
1495 std::vector<std::vector<
unsigned int >> groupRowVectors =
1496 getGroupRowsInVectors(groupIdCol, groupID, onlyStatusTrue, orderedByPriority);
1498 for(
const auto& groupRowVector : groupRowVectors)
1499 for(
const auto& groupRow : groupRowVector)
1500 retVector.push_back(groupRow);
1512 const unsigned int groupIdCol,
1513 const std::string& groupID,
1514 bool onlyStatusTrue )
const
1516 return getGroupRowsInVectors(
1517 groupIdCol, groupID, onlyStatusTrue,
true );
1528 std::vector<std::vector<
unsigned int >> TableView::getGroupRowsInVectors(
1529 const unsigned int groupIdCol,
1530 const std::string& groupID,
1531 bool onlyStatusTrue,
1532 bool orderedByPriority)
const
1534 std::map<uint64_t , std::vector<
unsigned int >>
1536 std::vector<std::vector<
unsigned int >> retVector;
1537 uint64_t tmpPriority;
1540 if(!(orderedByPriority &&
1541 colPriority_ != INVALID))
1542 retVector.push_back(std::vector<unsigned int /*group row*/>());
1544 __COUTS__(2) <<
"getGroupRowsInVectors: " << groupID <<
" at col " << groupIdCol
1546 for(
unsigned int r = 0; r < getNumberOfRows(); ++r)
1547 if(groupID ==
"" || groupID ==
"*" || groupIdCol == INVALID ||
1548 isEntryInGroupCol(r, groupIdCol, groupID))
1550 if(groupIdCol != INVALID)
1551 __COUTS__(2) <<
"Row " << r <<
" '" << getDataView()[r][groupIdCol]
1552 <<
"' is in group " << groupID << __E__;
1554 if(onlyStatusTrue && colStatus_ != INVALID)
1556 getValue(tmpStatus, r, colStatus_);
1562 if(orderedByPriority && colPriority_ != INVALID)
1564 getValue(tmpPriority, r, colPriority_);
1566 mapByPriority[tmpPriority ? tmpPriority : 100].push_back(r);
1569 retVector[0].push_back(r);
1572 __COUTS__(2) <<
"Row " << r <<
" '" << getDataView()[r][groupIdCol]
1573 <<
"' is NOT in group " << groupID << __E__;
1575 if(orderedByPriority && colPriority_ != INVALID)
1579 for(
const auto& priorityChildRowVector : mapByPriority)
1581 retVector.push_back(std::vector<unsigned int /*group row*/>());
1582 for(
const auto& priorityChildRow : priorityChildRowVector.second)
1583 retVector[retVector.size() - 1].push_back(priorityChildRow);
1586 __COUT__ <<
"Returning priority children list." << __E__;
1599 const unsigned int& col,
1600 const std::string& groupNeedle,
1601 bool deleteRowIfNoGroupLeft)
1603 __COUT__ <<
"removeRowFromGroup groupNeedle " << groupNeedle << __E__;
1604 std::set<std::string> groupIDList;
1605 if(!isEntryInGroupCol(row, col, groupNeedle, &groupIDList))
1607 __SS__ <<
"GroupID (" << groupNeedle <<
") removed from row (" << row
1608 <<
") was already removed!" << __E__;
1617 std::string newValue =
"";
1618 unsigned int cnt = 0;
1619 for(
const auto& groupID : groupIDList)
1621 __COUTT__ << groupID <<
" " << groupNeedle <<
" " << newValue << __E__;
1622 if(groupID == groupNeedle)
1627 newValue += groupID;
1630 bool wasDeleted =
false;
1631 if(deleteRowIfNoGroupLeft && newValue ==
"")
1633 __COUTT__ <<
"Delete row since it no longer part of any group." << __E__;
1640 __COUTT__ << getDataView()[row][col] << __E__;
1653 const std::string& childLinkIndex,
1654 const std::string& groupNeedle)
const
1658 return isEntryInGroupCol(r, c, groupNeedle);
1670 bool TableView::isEntryInGroupCol(
const unsigned int& r,
1671 const unsigned int& c,
1672 const std::string& groupNeedle,
1673 std::set<std::string>* groupIDList)
const
1675 if(r >= getNumberOfRows() || c >= getNumberOfColumns())
1677 __SS__ <<
"Invalid row/col requested!" << __E__;
1686 __COUTT__ <<
"groupNeedle " << groupNeedle << __E__;
1689 for(; j < theDataView_[r][c].size(); ++j)
1690 if((theDataView_[r][c][j] ==
' ' ||
1691 theDataView_[r][c][j] ==
'|') &&
1694 else if((theDataView_[r][c][j] ==
1696 theDataView_[r][c][j] ==
'|') &&
1700 groupIDList->emplace(theDataView_[r][c].substr(i, j - i));
1702 __COUTT__ <<
"Group found to compare: " << theDataView_[r][c].substr(i, j - i)
1704 if(groupIDList ? groupNeedle == theDataView_[r][c].substr(i, j - i)
1706 theDataView_[r][c].substr(i, j - i), groupNeedle))
1708 __COUTT__ <<
"'" << theDataView_[r][c].substr(i, j - i)
1709 <<
"' is in group '" << groupNeedle <<
"'!" << __E__;
1721 groupIDList->emplace(theDataView_[r][c].substr(i, j - i));
1723 __COUTT__ <<
"Group found to compare: " << theDataView_[r][c].substr(i, j - i)
1725 if(groupIDList ? groupNeedle == theDataView_[r][c].substr(i, j - i)
1729 __COUTT__ <<
"'" << theDataView_[r][c].substr(i, j - i) <<
"' is in group '"
1730 << groupNeedle <<
"'!" << __E__;
1747 unsigned int r)
const
1752 unsigned int r)
const
1756 std::set<std::string> retSet;
1761 if(r != (
unsigned int)-1)
1763 if(r >= getNumberOfRows())
1765 __SS__ <<
"Invalid row requested!" << __E__;
1797 for(r = 0; r < getNumberOfRows(); ++r)
1849 if(!childLinkIndex.size())
1851 __SS__ <<
"Empty childLinkIndex string parameter!" << __E__;
1856 const char* needleChildLinkIndex = &childLinkIndex[0];
1860 size_t spacePos = childLinkIndex.find(
' ');
1861 if(spacePos != std::string::npos &&
1862 spacePos + 1 < childLinkIndex.size())
1865 needleChildLinkIndex = &childLinkIndex[spacePos + 1];
1868 std::map<std::string, unsigned int>::const_iterator it =
1869 colLinkGroupIDs_.find(needleChildLinkIndex);
1871 colLinkGroupIDs_.end())
1875 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1878 if(columnsInfo_[col].isChildLink() || columnsInfo_[col].isChildLinkUID() ||
1879 columnsInfo_[col].isChildLinkGroupID() || columnsInfo_[col].isGroupID())
1881 if(needleChildLinkIndex == columnsInfo_[col].getChildLinkIndex())
1887 <<
"Error! Incompatible table for this group link! Table '" << tableName_
1888 <<
"' is missing a GroupID column with data type '"
1889 << TableViewColumnInfo::TYPE_START_GROUP_ID <<
"-" << needleChildLinkIndex
1891 <<
"Note: you can separate the child GroupID column data type from "
1892 <<
"the parent GroupLink column data type; this is accomplished by using a space "
1893 <<
"character at the parent level - the string after the space will be treated "
1895 <<
"child GroupID column data type." << __E__;
1896 ss <<
"Existing Column GroupIDs: " << __E__;
1897 for(
auto& groupIdColPair : colLinkGroupIDs_)
1898 ss <<
"\t" << groupIdColPair.first <<
" : col-" << groupIdColPair.second << __E__;
1900 ss <<
"Existing Column Types: " << __E__;
1901 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1902 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1912 const std::string& value,
1913 unsigned int offsetRow,
1914 bool doNotThrow )
const
1916 for(
unsigned int row = offsetRow; row < theDataView_.size(); ++row)
1918 if(theDataView_[row][col] == value)
1922 return TableView::INVALID;
1924 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find value=" << value
1925 <<
" in column named " << columnsInfo_[col].getName()
1926 <<
" with type=" << columnsInfo_[col].getType() << __E__ << __E__
1937 const std::string& value,
1938 const std::string& groupId,
1939 const std::string& childLinkIndex,
1940 unsigned int offsetRow)
const
1943 for(
unsigned int row = offsetRow; row < theDataView_.size(); ++row)
1945 if(theDataView_[row][col] == value && isEntryInGroupCol(row, groupIdCol, groupId))
1949 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find in group the value=" << value
1950 <<
" in column named '" << columnsInfo_[col].getName()
1951 <<
"' with type=" << columnsInfo_[col].getType() <<
" and GroupID: '"
1952 << groupId <<
"' in column '" << groupIdCol
1953 <<
"' with GroupID child link index '" << childLinkIndex <<
"'" << __E__;
1964 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1966 columnsInfo_[col].getName() ))
1969 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find column named '" << wildCardName
1971 ss <<
"Existing columns:\n";
1972 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1973 ss <<
"\t" << columnsInfo_[col].getName() <<
"\n";
1986 unsigned int startingCol)
const
1988 for(
unsigned int col = startingCol; col < columnsInfo_.size(); ++col)
1990 __COUTS__(40) << columnsInfo_[col].getType() << __E__;
1991 if(columnsInfo_[col].getType() == type)
2005 if(!getNumberOfRows())
2006 return getNumberOfColumns();
2007 return theDataView_[0].size();
2011 std::set<std::string> TableView::getColumnNames(
void)
const
2013 std::set<std::string> retSet;
2014 for(
auto& colInfo : columnsInfo_)
2015 retSet.emplace(colInfo.getName());
2020 std::map<std::string,
unsigned int > TableView::getColumnNamesMap(
void)
const
2022 std::map<std::string,
unsigned int > retMap;
2024 for(
auto& colInfo : columnsInfo_)
2025 retMap.emplace(std::make_pair(colInfo.getName(), c++));
2030 std::set<std::string> TableView::getColumnStorageNames(
void)
const
2032 std::set<std::string> retSet;
2033 for(
auto& colInfo : columnsInfo_)
2034 retSet.emplace(colInfo.getStorageName());
2039 const std::vector<std::string>& TableView::initRowDefaults(
void)
2041 std::vector<std::string>& retVec = rowDefaultValues_;
2045 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
2052 if(columnsInfo_[col].isChildLink())
2054 const std::vector<std::string>& theDataChoices =
2055 columnsInfo_[col].getDataChoices();
2058 if(!theDataChoices.size() ||
2059 theDataChoices[0] ==
"arbitraryBool=1")
2060 retVec.push_back(columnsInfo_[col].getDefaultValue());
2064 (theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=0");
2069 bool foundDefault =
false;
2071 for(
const auto& choice : theDataChoices)
2072 if(skipOne && !hasSkipped)
2077 else if(choice == columnsInfo_[col].getDefaultValue())
2079 foundDefault =
true;
2084 if(!foundDefault && theDataChoices.size() > (skipOne ? 1 : 0))
2085 retVec.push_back(theDataChoices[(skipOne ? 1 : 0)]);
2087 retVec.push_back(columnsInfo_[col].getDefaultValue());
2091 retVec.push_back(columnsInfo_[col].getDefaultValue());
2096 return rowDefaultValues_;
2102 if(column >= columnsInfo_.size())
2104 __SS__ <<
"\nCan't find column " << column
2105 <<
"\n\n\n\nThe column info is likely missing due to incomplete "
2106 "Configuration View filling.\n\n"
2111 return columnsInfo_[column];
2123 void TableView::setAuthor(
const std::string& author) { author_ = author; }
2126 void TableView::setCreationTime(time_t t) { creationTime_ = t; }
2129 void TableView::setLastAccessTime(time_t t) { lastAccessTime_ = t; }
2132 void TableView::setLooseColumnMatching(
bool setValue)
2134 fillWithLooseColumnMatching_ =
setValue;
2138 void TableView::doGetSourceRawData(
bool setValue) { getSourceRawData_ =
setValue; }
2141 void TableView::reset(
void)
2146 columnsInfo_.clear();
2147 theDataView_.clear();
2151 void TableView::print(std::ostream& out )
const
2153 out <<
"============================================================================="
2156 out <<
"Print: " << tableName_ <<
" Version: " << version_ <<
" Comment: " << comment_
2157 <<
" Author: " << author_ <<
" Creation Time: " << ctime(&creationTime_) << __E__;
2158 out <<
"\t\tNumber of Cols " << getNumberOfColumns() << __E__;
2159 out <<
"\t\tNumber of Rows " << getNumberOfRows() << __E__;
2161 out <<
"Columns:\t";
2162 for(
int i = 0; i < (int)columnsInfo_.size(); ++i)
2163 out << i <<
":" << columnsInfo_[i].getName() <<
":"
2164 << columnsInfo_[i].getStorageName() <<
":" << columnsInfo_[i].getType() <<
":"
2165 << columnsInfo_[i].getDataType() <<
"\t ";
2168 out <<
"Rows:" << __E__;
2171 for(
int r = 0; r < (int)getNumberOfRows(); ++r)
2173 out << (int)r <<
":\t";
2174 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
2176 out << (int)c <<
":";
2179 if(columnsInfo_[c].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
2181 int choiceIndex = -1;
2182 std::vector<std::string> choices = columnsInfo_[c].getDataChoices();
2185 if(val == columnsInfo_[c].getDefaultValue())
2189 for(
int i = 0; i < (int)choices.size(); ++i)
2190 if(val == choices[i])
2191 choiceIndex = i + 1;
2194 out <<
"ChoiceIndex=" << choiceIndex <<
":";
2197 out << theDataView_[r][c];
2217 void TableView::printJSON(std::ostream& out )
const
2220 std::string tmpCachePrepend = TableBase::GROUP_CACHE_PREPEND;
2222 std::string tmpJsonDocPrepend = TableBase::JSON_DOC_PREPEND;
2224 __COUTS__(32) <<
" '" << tableName_ <<
"' vs " << tmpCachePrepend <<
" or "
2225 << tmpJsonDocPrepend << __E__;
2227 if(tableName_.substr(0, tmpCachePrepend.length()) == tmpCachePrepend ||
2228 tableName_.substr(0, tmpJsonDocPrepend.length()) == tmpJsonDocPrepend)
2236 out <<
"\"NAME\" : \"" << tableName_ <<
"\",\n";
2240 out <<
"\"COMMENT\" : ";
2246 for(
unsigned int i = 0; i < val.size(); ++i)
2250 else if(val[i] ==
'\t')
2252 else if(val[i] ==
'\r')
2257 if(val[i] ==
'"' || val[i] ==
'\\')
2264 out <<
"\"AUTHOR\" : \"" << author_ <<
"\",\n";
2265 out <<
"\"CREATION_TIME\" : " << creationTime_ <<
",\n";
2270 out <<
"\"COL_TYPES\" : {\n";
2271 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
2273 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
2274 out <<
"\"" << columnsInfo_[c].getDataType() <<
"\"";
2275 if(c + 1 < (
int)getNumberOfColumns())
2281 out <<
"\"DATA_SET\" : [\n";
2283 for(
int r = 0; r < (int)getNumberOfRows(); ++r)
2286 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
2288 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
2293 if(c + 1 < (
int)getNumberOfColumns())
2298 if(r + 1 < (
int)getNumberOfRows())
2308 void TableView::printCSV(std::ostream& out ,
2309 const std::string& valueDelimeter ,
2310 const std::string& recordDelimeter ,
2311 bool includeColumnNames )
const
2314 std::string tmpCachePrepend = TableBase::GROUP_CACHE_PREPEND;
2316 std::string tmpJsonDocPrepend = TableBase::JSON_DOC_PREPEND;
2318 __COUTS__(32) <<
" '" << tableName_ <<
"' vs " << tmpCachePrepend <<
" or "
2319 << tmpJsonDocPrepend << __E__;
2321 if(tableName_.substr(0, tmpCachePrepend.length()) == tmpCachePrepend ||
2322 tableName_.substr(0, tmpJsonDocPrepend.length()) == tmpJsonDocPrepend)
2324 __SS__ <<
"Cannot convert custom storage data to CSV!" << __E__;
2331 for(
int c = 0; includeColumnNames && c < (int)getNumberOfColumns(); ++c)
2334 out << valueDelimeter;
2335 out <<
"\"" << columnsInfo_[c].getStorageName() <<
"\"";
2337 if(includeColumnNames)
2338 out << recordDelimeter;
2340 for(
int r = 0; r < (int)getNumberOfRows(); ++r)
2342 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
2345 out << valueDelimeter;
2350 out << recordDelimeter;
2366 std::string tmpCachePrepend = TableBase::GROUP_CACHE_PREPEND;
2368 std::string tmpJsonDocPrepend = TableBase::JSON_DOC_PREPEND;
2372 if(tableName_.substr(0, tmpJsonDocPrepend.length()) == tmpJsonDocPrepend ||
2373 tableName_.substr(0, tmpCachePrepend.length()) == tmpCachePrepend)
2375 __COUTS__(3) <<
"Special JSON doc: " << json << __E__;
2382 bool rawData = getSourceRawData_;
2383 if(getSourceRawData_)
2385 __COUTV__(getSourceRawData_);
2386 getSourceRawData_ =
false;
2387 sourceRawData_ =
"";
2390 std::map<std::string ,
unsigned int > keyEntryCountMap;
2391 std::vector<std::string> keys;
2392 keys.push_back(
"NAME");
2393 keys.push_back(
"COMMENT");
2394 keys.push_back(
"AUTHOR");
2395 keys.push_back(
"CREATION_TIME");
2397 keys.push_back(
"DATA_SET");
2401 CV_JSON_FILL_COMMENT,
2402 CV_JSON_FILL_AUTHOR,
2403 CV_JSON_FILL_CREATION_TIME,
2405 CV_JSON_FILL_DATA_SET
2410 __COUTV__(tableName_);
2411 __COUTTV__(getNumberOfRows());
2415 sourceColumnMismatchCount_ = 0;
2416 sourceColumnMissingCount_ = 0;
2417 sourceColumnNames_.clear();
2418 unsigned int colFoundCount = 0;
2420 unsigned int row = -1;
2421 unsigned int colSpeedup = 0;
2422 unsigned int startString, startNumber = 0, endNumber = -1;
2423 unsigned int bracketCount = 0;
2424 unsigned int sqBracketCount = 0;
2429 bool keyIsMatch, keyIsComment;
2430 unsigned int keyIsMatchIndex, keyIsMatchStorageIndex, keyIsMatchCommentIndex;
2431 const std::string COMMENT_ALT_KEY =
"COMMENT";
2433 std::string extractedString =
"", currKey =
"", currVal =
"";
2434 unsigned int currDepth = 0;
2436 std::vector<std::string> jsonPath;
2437 std::vector<char> jsonPathType;
2438 char lastPopType =
'_';
2440 unsigned int matchedKey = -1;
2441 unsigned int lastCol = -1;
2444 for(; i < json.size(); ++i)
2449 if(i - 1 < json.size() &&
2450 json[i - 1] ==
'\\')
2453 inQuotes = !inQuotes;
2459 json.substr(startString + 1, i - startString - 1));
2468 if(jsonPathType[jsonPathType.size() - 1] !=
'{' ||
2471 __COUT__ <<
"Invalid ':' position" << __E__;
2476 jsonPathType.push_back(
'K');
2477 jsonPath.push_back(extractedString);
2496 if(lastPopType ==
'{')
2499 if(jsonPathType[jsonPathType.size() - 1] ==
'K')
2502 jsonPath.pop_back();
2503 jsonPathType.pop_back();
2509 currVal = extractedString;
2512 if(endNumber == (
unsigned int)-1 ||
2513 endNumber <= startNumber)
2516 if(endNumber <= startNumber)
2519 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
2522 currDepth = bracketCount;
2524 if(jsonPathType[jsonPathType.size() - 1] ==
'K')
2526 currKey = jsonPath[jsonPathType.size() - 1];
2531 jsonPath.pop_back();
2532 jsonPathType.pop_back();
2534 else if(jsonPathType[jsonPathType.size() - 1] ==
2538 for(
unsigned int k = jsonPathType.size() - 2; k < jsonPathType.size();
2540 if(jsonPathType[k] ==
'K')
2542 currKey = jsonPath[k];
2547 __COUT__ <<
"Invalid array position" << __E__;
2556 __COUT__ <<
"Invalid ',' position" << __E__;
2567 jsonPathType.push_back(
'{');
2568 jsonPath.push_back(
"{");
2581 if(lastPopType !=
'{' &&
2582 jsonPathType[jsonPathType.size() - 1] ==
'K')
2584 currDepth = bracketCount;
2585 currKey = jsonPath[jsonPathType.size() - 1];
2587 currVal = extractedString;
2590 if(endNumber == (
unsigned int)-1 ||
2591 endNumber <= startNumber)
2594 if(endNumber <= startNumber)
2598 json.substr(startNumber + 1, endNumber - startNumber - 1);
2602 jsonPath.pop_back();
2603 jsonPathType.pop_back();
2606 if(jsonPathType[jsonPathType.size() - 1] !=
'{')
2608 __COUT__ <<
"Invalid '}' position" << __E__;
2612 jsonPath.pop_back();
2613 jsonPathType.pop_back();
2619 jsonPathType.push_back(
'[');
2620 jsonPath.push_back(
"[");
2629 if(jsonPathType[jsonPathType.size() - 1] !=
'[')
2631 __COUT__ <<
"Invalid ']' position" << __E__;
2635 currDepth = bracketCount;
2639 currVal = extractedString;
2642 if(endNumber == (
unsigned int)-1 ||
2643 endNumber <= startNumber)
2646 if(endNumber <= startNumber)
2649 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
2654 for(
unsigned int k = jsonPathType.size() - 2; k < jsonPathType.size(); --k)
2655 if(jsonPathType[k] ==
'K')
2657 currKey = jsonPath[k];
2662 __COUT__ <<
"Invalid array position" << __E__;
2667 if(jsonPathType[jsonPathType.size() - 1] !=
'[')
2669 __COUT__ <<
"Invalid ']' position" << __E__;
2673 jsonPath.pop_back();
2674 jsonPathType.pop_back();
2683 if(startNumber != (
unsigned int)-1 && endNumber == (
unsigned int)-1)
2697 std::cout << i <<
":\t" << json[i] <<
" - ";
2707 std::cout <<
"ExtKey=";
2708 for(
unsigned int k = 0; k < jsonPath.size(); ++k)
2709 std::cout << jsonPath[k] <<
"/";
2711 std::cout << lastPopType <<
" ";
2712 std::cout << bracketCount <<
" ";
2713 std::cout << sqBracketCount <<
" ";
2714 std::cout << inQuotes <<
" ";
2715 std::cout << newValue <<
"-";
2716 std::cout << currKey <<
"-{" << currDepth <<
"}:";
2717 std::cout << currVal <<
" ";
2718 std::cout << startNumber <<
"-";
2719 std::cout << endNumber <<
" ";
2721 __COUTTV__(fillWithLooseColumnMatching_);
2722 __COUTTV__(getNumberOfRows());
2731 for(
unsigned int k = 0; k < keys.size(); ++k)
2732 if((currDepth == 1 && keys[k] == currKey) ||
2733 (currDepth > 1 && keys[k] == jsonPath[1]))
2742 if(matchedKey == CV_JSON_FILL_COMMENT)
2743 setComment(currVal);
2744 else if(matchedKey == CV_JSON_FILL_AUTHOR)
2746 else if(matchedKey == CV_JSON_FILL_CREATION_TIME)
2747 setCreationTime(strtol(currVal.c_str(), 0, 10));
2749 else if(currDepth == 2)
2752 sourceRawData_ += StringMacros::encodeURIComponent(currKey) +
"," +
2753 StringMacros::encodeURIComponent(currVal) +
",";
2754 sourceColumnNames_.emplace(currKey);
2757 else if(matchedKey != (
unsigned int)-1)
2760 __COUTT__ <<
"New Data for:: key[" << matchedKey <<
"]-"
2761 << keys[matchedKey] <<
"\n";
2765 case CV_JSON_FILL_NAME:
2771 if(currVal != getTableName() &&
2773 "TABLE_GROUP_METADATA")
2774 __COUT_WARN__ <<
"JSON-fill Table name mismatch: " << currVal
2775 <<
" vs " << getTableName() << __E__;
2778 case CV_JSON_FILL_COMMENT:
2780 setComment(currVal);
2782 case CV_JSON_FILL_AUTHOR:
2786 case CV_JSON_FILL_CREATION_TIME:
2788 setCreationTime(strtol(currVal.c_str(), 0, 10));
2793 case CV_JSON_FILL_DATA_SET:
2795 __COUTT__ <<
"CV_JSON_FILL_DATA_SET New Data for::" << matchedKey
2796 <<
"]-" << keys[matchedKey] <<
"/" << currDepth
2797 <<
".../" << currKey <<
"\n";
2803 unsigned int col, ccnt = 0;
2804 unsigned int noc = getNumberOfColumns();
2805 for(; ccnt < noc; ++ccnt)
2811 if(fillWithLooseColumnMatching_)
2824 if(getNumberOfRows() == 1)
2825 sourceColumnNames_.emplace(currKey);
2829 if(row >= getNumberOfRows())
2831 __SS__ <<
"Invalid row"
2833 std::cout << ss.str();
2838 theDataView_[row][col] =
2846 col = (ccnt + colSpeedup) % noc;
2852 keyIsComment =
true;
2853 for(keyIsMatchIndex = 0,
2854 keyIsMatchStorageIndex = 0,
2855 keyIsMatchCommentIndex = 0;
2856 keyIsMatchIndex < currKey.size();
2859 if(columnsInfo_[col]
2860 .getStorageName()[keyIsMatchStorageIndex] ==
2862 ++keyIsMatchStorageIndex;
2864 if(currKey[keyIsMatchIndex] ==
'_')
2868 if(keyIsMatchStorageIndex >=
2869 columnsInfo_[col].getStorageName().size() ||
2870 currKey[keyIsMatchIndex] !=
2872 .getStorageName()[keyIsMatchStorageIndex])
2882 keyIsMatchCommentIndex < COMMENT_ALT_KEY.size())
2884 if(currKey[keyIsMatchIndex] !=
2885 COMMENT_ALT_KEY[keyIsMatchCommentIndex])
2888 keyIsComment =
false;
2892 ++keyIsMatchStorageIndex;
2897 __COUTTV__(keyIsMatch);
2898 __COUTTV__(keyIsComment);
2899 __COUTTV__(currKey);
2900 __COUTTV__(columnsInfo_[col].getStorageName());
2901 __COUTTV__(getNumberOfRows());
2904 if(keyIsMatch || keyIsComment)
2907 if(keyEntryCountMap.find(currKey) ==
2908 keyEntryCountMap.end())
2909 keyEntryCountMap[currKey] =
2912 ++keyEntryCountMap.at(currKey);
2915 if(keyEntryCountMap.size() == 1 ||
2916 (keyEntryCountMap.at(currKey) &&
2917 keyEntryCountMap.at(currKey) >
2920 if(getNumberOfRows())
2921 sourceColumnMissingCount_ +=
2922 getNumberOfColumns() - colFoundCount;
2930 if(getNumberOfRows() == 1)
2931 sourceColumnNames_.emplace(currKey);
2935 if(row >= getNumberOfRows())
2937 __SS__ <<
"Invalid row"
2939 __COUT__ <<
"\n" << ss.str();
2944 theDataView_[row][col] = currVal;
2950 if(ccnt >= getNumberOfColumns())
2953 <<
"Invalid column in JSON source data: " << currKey
2954 <<
" not found in column names of table named "
2955 << getTableName() <<
"."
2960 ++sourceColumnMismatchCount_;
2961 if(getNumberOfRows() ==
2963 sourceColumnNames_.emplace(currKey);
2966 __COUT_WARN__ <<
"Trying to ignore error, and not populating "
2971 colSpeedup = (colSpeedup + 1) % noc;
2990 __COUTTV__(fillWithLooseColumnMatching_);
2991 __COUTTV__(sourceColumnNames_.size());
2994 if(!fillWithLooseColumnMatching_ && sourceColumnMissingCount_ > 0)
2996 __COUTV__(sourceColumnMissingCount_);
2997 __SS__ <<
"Can not ignore errors because not every column was found in the "
2999 <<
". Please see the details below:\n\n"
3004 if(sourceColumnNames_.size() ==
3007 for(
unsigned int i = 0; i < getNumberOfColumns(); ++i)
3008 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
3017 std::string TableView::getMismatchColumnInfo(
void)
const
3019 const std::set<std::string>& srcColNames = getSourceColumnNames();
3020 std::set<std::string> destColNames = getColumnStorageNames();
3022 __SS__ <<
"The source column size was found to be " << srcColNames.size()
3023 <<
", and the current number of columns for this table is "
3024 << getNumberOfColumns() <<
". This resulted in a count of "
3025 << getSourceColumnMismatch() <<
" source column mismatches, and a count of "
3026 << getSourceColumnMissing() <<
" table entries missing in "
3027 << getNumberOfRows() <<
" row(s) of data." << __E__;
3030 << srcColNames.size()
3031 <<
" Source column names in ALPHABETICAL order were as follows:\n";
3033 std::string preIndexStr =
"";
3034 for(
auto& srcColName : srcColNames)
3036 if(destColNames.find(srcColName) == destColNames.end())
3037 ss <<
"\n\t*** " << preIndexStr << index <<
". " << srcColName <<
" ***";
3039 ss <<
"\n\t" << preIndexStr << index <<
". " << srcColName;
3052 << destColNames.size()
3053 <<
" Current table column names in ALPHABETICAL order are as follows:\n";
3056 for(
auto& destColName : destColNames)
3058 if(srcColNames.find(destColName) == srcColNames.end())
3059 ss <<
"\n\t*** " << preIndexStr << index <<
". " << destColName <<
" ***";
3061 ss <<
"\n\t" << preIndexStr << index <<
". " << destColName;
3076 bool TableView::isURIEncodedCommentTheSame(
const std::string& comment)
const
3079 return comment_ == compareStr;
3124 const int& dataOffset ,
3125 const std::string& author ,
3126 const char rowDelimter ,
3127 const char colDelimter )
3129 int row = dataOffset;
3131 std::string currentValue =
"";
3132 bool insideQuotes =
false;
3133 int authorCol =
findColByType(TableViewColumnInfo::TYPE_AUTHOR);
3134 int timestampCol =
findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
3136 for(
size_t i = 0; i < data.size(); ++i)
3139 const char nextChar = (i + 1 < data.size() ? data[i + 1] :
' ');
3143 if(insideQuotes && nextChar ==
'"')
3146 currentValue +=
'"';
3152 insideQuotes = !insideQuotes;
3155 else if(c == rowDelimter && !insideQuotes)
3157 if(col == 0 && row >= (
int)getNumberOfRows())
3163 else if((c == colDelimter || c ==
'\r') && !insideQuotes)
3173 __COUT__ <<
"First row detected as column names." << __E__;
3181 setValue(time(0), row, timestampCol);
3205 __COUT__ <<
"First row detected as column names." << __E__;
3213 setValue(time(0), row, timestampCol);
3252 const int& dataOffset,
3253 const std::string& author)
3261 int j = data.find(
',', i);
3262 int k = data.find(
';', i);
3264 bool rowWasModified;
3265 unsigned int countRowsModified = 0;
3266 int authorCol =
findColByType(TableViewColumnInfo::TYPE_AUTHOR);
3267 int timestampCol =
findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
3270 while(k != (
int)(std::string::npos))
3272 rowWasModified =
false;
3273 if(r >= (
int)getNumberOfRows())
3277 rowWasModified =
true;
3280 while(j < k && j != (
int)(std::string::npos))
3285 if(c >= (
int)getNumberOfColumns() - 2)
3288 j = data.find(
',', i);
3294 rowWasModified =
true;
3297 j = data.find(
',', i);
3302 if(author !=
"" && rowWasModified)
3304 __COUTT__ <<
"Row=" << (int)r <<
" was modified!" << __E__;
3306 setValue(time(0), r, timestampCol);
3310 ++countRowsModified;
3316 j = data.find(
',', i);
3317 k = data.find(
';', i);
3321 while(r < (
int)getNumberOfRows())
3324 __COUT__ <<
"Row deleted: " << (int)r << __E__;
3325 ++countRowsModified;
3328 __COUT_INFO__ <<
"countRowsModified=" << countRowsModified << __E__;
3330 if(!countRowsModified)
3335 bool match = getColumnStorageNames().size() == getSourceColumnNames().size();
3338 for(
auto& destColName : getColumnStorageNames())
3339 if(getSourceColumnNames().find(destColName) ==
3340 getSourceColumnNames().end())
3342 __COUT__ <<
"Found column name mismach for '" << destColName
3343 <<
"'... So allowing same data!" << __E__;
3352 __SS__ <<
"No rows were modified! No reason to fill a view with same content."
3354 __COUT__ <<
"\n" << ss.str();
3364 sourceColumnNames_.clear();
3365 for(
unsigned int i = 0; i < getNumberOfColumns(); ++i)
3366 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
3388 const unsigned int& r,
3389 const unsigned int& c,
3390 const std::string& author)
3392 if(!(c < columnsInfo_.size() && r < getNumberOfRows()))
3394 __SS__ <<
"Invalid row (" << (int)r <<
") col (" << (
int)c <<
") requested!"
3395 <<
"Number of Rows = " << getNumberOfRows()
3396 <<
"Number of Columns = " << columnsInfo_.size() << __E__;
3402 std::string originalValueStr =
3426 theDataView_[r][c] = valueStr;
3430 else if(columnsInfo_[c].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
3442 setValue(time_t(strtol(valueStr.c_str(), 0, 10)), r, c);
3445 theDataView_[r][c] = valueStr;
3447 bool rowWasModified =
3448 (originalValueStr !=
3452 if(author !=
"" && rowWasModified)
3454 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << __E__;
3455 int authorCol =
findColByType(TableViewColumnInfo::TYPE_AUTHOR);
3456 int timestampCol =
findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
3458 setValue(time(0), r, timestampCol);
3461 return rowWasModified;
3465 void TableView::resizeDataView(
unsigned int nRows,
unsigned int nCols)
3469 theDataView_.resize(nRows, std::vector<std::string>(nCols));
3480 const std::string& author,
3482 incrementUniqueData ,
3485 const std::string& baseNameAutoUID ,
3486 unsigned int rowToAdd ,
3487 std::string childLinkIndex ,
3488 std::string groupId )
3491 if(rowToAdd == (
unsigned int)-1)
3492 rowToAdd = getNumberOfRows();
3494 theDataView_.resize(getNumberOfRows() + 1,
3495 std::vector<std::string>(getNumberOfColumns()));
3498 for(
unsigned int r = getNumberOfRows() - 2; r >= rowToAdd; --r)
3500 if(r == (
unsigned int)-1)
3502 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
3503 theDataView_[r + 1][col] = theDataView_[r][col];
3506 std::vector<std::string> defaultRowValues = getDefaultRowValues();
3509 std::string tmpString, baseString;
3513 std::string numString;
3518 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
3526 if(incrementUniqueData &&
3527 (col ==
getColUID() || columnsInfo_[col].isChildLinkGroupID() ||
3528 (getNumberOfRows() > 1 &&
3529 (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_DATA ||
3530 columnsInfo_[col].getType() ==
3531 TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA))))
3533 if(col ==
getColUID() || columnsInfo_[col].isChildLinkGroupID())
3535 rowToAdd, col, baseNameAutoUID );
3545 theDataView_[rowToAdd][col] = defaultRowValues[col];
3550 __COUT__ <<
"Row=" << rowToAdd <<
" was created!" << __E__;
3552 int authorCol =
findColByType(TableViewColumnInfo::TYPE_AUTHOR);
3553 int timestampCol =
findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
3554 setValue(author, rowToAdd, authorCol);
3555 setValue(time(0), rowToAdd, timestampCol);
3566 if(r >= (
int)getNumberOfRows())
3569 __SS__ <<
"Row " << (int)r
3570 <<
" is out of bounds (Row Count = " << getNumberOfRows()
3571 <<
") and can not be deleted." << __E__;
3575 theDataView_.erase(theDataView_.begin() + r);
3595 const unsigned int& c,
3597 std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>& linkPair)
const
3599 if(!(c < columnsInfo_.size()))
3601 __SS__ <<
"Invalid col (" << (int)c <<
") requested for child link!" << __E__;
3609 if((isGroup = columnsInfo_[c].isChildLinkGroupID()) ||
3610 columnsInfo_[c].isChildLinkUID())
3614 linkPair.second = c;
3615 std::string index = columnsInfo_[c].getChildLinkIndex();
3620 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
3626 else if(columnsInfo_[col].isChildLink() &&
3627 index == columnsInfo_[col].getChildLinkIndex())
3632 linkPair.first = col;
3638 __SS__ <<
"\tIn view: " << tableName_
3639 <<
", Can't find complete child link for column name "
3640 << columnsInfo_[c].getName() << __E__;
3644 if(!columnsInfo_[c].isChildLink())
3649 std::string index = columnsInfo_[c].getChildLinkIndex();
3654 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
3671 if(((columnsInfo_[col].isChildLinkUID() && !(isGroup =
false)) ||
3672 (columnsInfo_[col].isChildLinkGroupID() && (isGroup =
true))) &&
3673 index == columnsInfo_[col].getChildLinkIndex())
3678 linkPair.second = col;
3684 __SS__ <<
"\tIn view: " << tableName_
3685 <<
", Can't find complete child link id for column name "
3686 << columnsInfo_[c].getName() << __E__;
static std::string convertToCaps(std::string &str, bool isConfigName=false)
static const std::string DATATYPE_NUMBER
static const std::string TYPE_UID
NOTE: Do NOT put '-' in static const TYPEs because it will mess up javascript handling in the web gui...
unsigned int findRow(unsigned int col, const T &value, unsigned int offsetRow=0, bool doNotThrow=false) const
< in included .icc source
std::string getEscapedValueAsString(unsigned int row, unsigned int col, bool convertEnvironmentVariables=true, bool quotesToDoubleQuotes=false) const
bool isEntryInGroup(const unsigned int &row, const std::string &childLinkIndex, const std::string &groupNeedle) const
void setValueAsString(const std::string &value, unsigned int row, unsigned int col)
std::vector< std::vector< unsigned int > > getGroupRowsByPriority(const unsigned int groupIdCol, const std::string &groupID, bool onlyStatusTrue=false) const
T validateValueForColumn(const std::string &value, unsigned int col, bool doConvertEnvironmentVariables=true) const
< in included .icc source
TableView(const std::string &tableName)
= "");
unsigned int getColStatus(void) const
unsigned int getLinkGroupIDColumn(const std::string &childLinkIndex) const
bool removeRowFromGroup(const unsigned int &row, const unsigned int &col, const std::string &groupID, bool deleteRowIfNoGroupLeft=false)
unsigned int findColByType(const std::string &type, unsigned int startingCol=0) const
bool getChildLink(const unsigned int &col, bool &isGroup, std::pair< unsigned int, unsigned int > &linkPair) const
void addRowToGroup(const unsigned int &row, const unsigned int &col, const std::string &groupID)
, const std::string& colDefault);
unsigned int copyRows(const std::string &author, const TableView &src, unsigned int srcOffsetRow=0, unsigned int srcRowsToCopy=(unsigned int) -1, unsigned int destOffsetRow=(unsigned int) -1, unsigned char generateUniqueDataColumns=false, const std::string &baseNameAutoUID="")
unsigned int getColPriority(void) const
const std::string & setUniqueColumnValue(unsigned int row, unsigned int col, std::string baseValueAsString="", bool doMathAppendStrategy=false, std::string childLinkIndex="", std::string groupId="")
std::string getValueAsString(unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const
std::vector< unsigned int > getGroupRows(const unsigned int groupIdCol, const std::string &groupID, bool onlyStatusTrue=false, bool orderedByPriority=false) const
const std::string & getCustomStorageData(void) const
Getters.
std::set< std::string > getSetOfGroupIDs(const std::string &childLinkIndex, unsigned int row=-1) const
void getValue(T &value, unsigned int row, unsigned int col, bool doConvertEnvironmentVariables=true) const
< in included .icc source
unsigned int getDataColumnSize(void) const
getDataColumnSize
int fillFromJSON(const std::string &json)
unsigned int getColUID(void) const
bool setURIEncodedValue(const std::string &value, const unsigned int &row, const unsigned int &col, const std::string &author="")
void fillFromCSV(const std::string &data, const int &dataOffset=0, const std::string &author="", const char rowDelimter=',', const char colDelimter='\n')
int fillFromEncodedCSV(const std::string &data, const int &dataOffset=0, const std::string &author="")
unsigned int findCol(const std::string &name) const
void setValue(const T &value, unsigned int row, unsigned int col)
< in included .icc source
void setURIEncodedComment(const std::string &uriComment)
unsigned int addRow(const std::string &author="", unsigned char incrementUniqueData=false, const std::string &baseNameAutoUID="", unsigned int rowToAdd=(unsigned int) -1, std::string childLinkIndex="", std::string groupId="")
unsigned int findRowInGroup(unsigned int col, const T &value, const std::string &groupId, const std::string &childLinkIndex, unsigned int offsetRow=0) const
< in included .icc source
void setCustomStorageData(const std::string &storageData)
defines used also by OtsConfigurationWizardSupervisor
static std::string getTimestampString(const std::string &linuxTimeInSeconds)
static const std::string & trim(std::string &s)
static void getSetFromString(const std::string &inputString, std::set< std::string > &setToReturn, const std::set< char > &delimiter={',', '|', '&'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'})
static std::string convertEnvironmentVariables(const std::string &data)
static std::string demangleTypeName(const char *name)
static std::string restoreJSONStringEntities(const std::string &str)
static bool wildCardMatch(const std::string &needle, const std::string &haystack, unsigned int *priorityIndex=0)
static std::string decodeURIComponent(const std::string &data)
static std::string stackTrace(void)
static bool getNumber(const std::string &s, T &retValue)