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 <<
"Source table=" << src.getTableName() <<
"_v" << src.getVersion()
145 <<
" cols=" << src.getNumberOfColumns() <<
" dest table=" << getTableName()
146 <<
"_v" << getVersion() <<
" cols=" << getNumberOfColumns() << __E__;
150 unsigned int srcRows = src.getNumberOfRows();
152 for(
unsigned int r = 0; r < srcRowsToCopy; ++r)
154 if(r + srcOffsetRow >= srcRows)
157 destOffsetRow =
addRow(author,
158 generateUniqueDataColumns ,
162 if(retRow == (
unsigned int)-1)
163 retRow = destOffsetRow;
166 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
167 if(generateUniqueDataColumns &&
169 columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_DATA ||
170 columnsInfo_[col].getType() ==
171 TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA))
175 __COUTT__ <<
"Copying [" << r + srcOffsetRow <<
"][" << col <<
"] to ["
176 << destOffsetRow <<
"][" << col
177 <<
"] = " << src.theDataView_[r + srcOffsetRow][col] << __E__;
178 theDataView_[destOffsetRow][col] =
179 src.theDataView_[r + srcOffsetRow][col];
204 std::set<std::string> colNameSet;
205 std::string capsColName, colName;
206 for(
auto& colInfo : columnsInfo_)
208 colName = colInfo.getStorageName();
209 if(colName ==
"COMMENT_DESCRIPTION")
212 for(
unsigned int i = 0; i < colName.size(); ++i)
214 if(colName[i] ==
'_')
216 capsColName += colName[i];
219 colNameSet.emplace(capsColName);
222 if(colNameSet.size() != columnsInfo_.size())
224 __SS__ <<
"Table Error:\t"
225 <<
" Columns names must be unique! There are " << columnsInfo_.size()
226 <<
" columns and the unique name count is " << colNameSet.size()
248 if(sourceColumnNames_.size() == 0)
249 for(
unsigned int i = 0; i < getNumberOfColumns(); ++i)
250 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
254 if((colPos =
findColByType(TableViewColumnInfo::TYPE_COMMENT)) != INVALID)
256 if(columnsInfo_[colPos].getName() != TableViewColumnInfo::COL_NAME_COMMENT)
258 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
259 <<
" data type column must have name="
260 << TableViewColumnInfo::COL_NAME_COMMENT << __E__;
264 if(
findColByType(TableViewColumnInfo::TYPE_COMMENT, colPos + 1) !=
267 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
268 <<
" data type in column " << columnsInfo_[colPos].getName()
269 <<
" is repeated. This is not allowed." << __E__;
273 if(colPos != getNumberOfColumns() - 3)
275 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
276 <<
" data type column must be 3rd to last (in column "
277 << getNumberOfColumns() - 3 <<
")." << __E__;
283 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
284 <<
" data type column "
285 <<
" is missing. This is not allowed." << __E__;
290 if((colPos =
findColByType(TableViewColumnInfo::TYPE_AUTHOR)) != INVALID)
292 if(
findColByType(TableViewColumnInfo::TYPE_AUTHOR, colPos + 1) !=
295 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR
296 <<
" data type in column " << columnsInfo_[colPos].getName()
297 <<
" is repeated. This is not allowed." << __E__;
301 if(colPos != getNumberOfColumns() - 2)
303 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR
304 <<
" data type column must be 2nd to last (in column "
305 << getNumberOfColumns() - 2 <<
")." << __E__;
311 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR
312 <<
" data type column "
313 <<
" is missing. This is not allowed." << __E__;
318 if((colPos =
findColByType(TableViewColumnInfo::TYPE_TIMESTAMP)) != INVALID)
320 if(
findColByType(TableViewColumnInfo::TYPE_TIMESTAMP, colPos + 1) !=
323 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP
324 <<
" data type in column " << columnsInfo_[colPos].getName()
325 <<
" is repeated. This is not allowed." << __E__;
329 if(colPos != getNumberOfColumns() - 1)
331 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP
332 <<
" data type column must be last (in column "
333 << getNumberOfColumns() - 1 <<
")." << __E__;
334 __COUT_ERR__ <<
"\n" << ss.str();
340 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP
341 <<
" data type column "
342 <<
" is missing. This is not allowed." << __E__;
349 std::set<std::string > uidSet;
350 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
352 if(uidSet.find(theDataView_[row][colUID_]) != uidSet.end())
354 __SS__ << (
"Entries in UID are not unique. Specifically at row=" +
355 std::to_string(row) +
" value=" + theDataView_[row][colUID_])
360 if(theDataView_[row][colUID_].size() == 0)
362 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' "
363 <<
" was identified. UIDs must contain at least 1 character."
368 for(
unsigned int i = 0; i < theDataView_[row][colUID_].size(); ++i)
369 if(!((theDataView_[row][colUID_][i] >=
'A' &&
370 theDataView_[row][colUID_][i] <=
'Z') ||
371 (theDataView_[row][colUID_][i] >=
'a' &&
372 theDataView_[row][colUID_][i] <=
'z') ||
373 (theDataView_[row][colUID_][i] >=
'0' &&
374 theDataView_[row][colUID_][i] <=
'9') ||
375 (theDataView_[row][colUID_][i] ==
'-' ||
376 theDataView_[row][colUID_][i] ==
'_')))
378 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' "
379 <<
" was identified. UIDs must contain only letters, numbers, "
380 <<
"dashes, and underscores." << __E__;
384 uidSet.insert(theDataView_[row][colUID_]);
386 if(uidSet.size() != getNumberOfRows())
388 __SS__ <<
"Entries in UID are not unique!"
389 <<
"There are " << getNumberOfRows()
390 <<
" records and the unique UID count is " << uidSet.size() << __E__;
395 colPos = (
unsigned int)-1;
396 while((colPos =
findColByType(TableViewColumnInfo::TYPE_UNIQUE_DATA,
397 colPos + 1)) != INVALID)
399 std::set<std::string > uDataSet;
400 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
402 if(uDataSet.find(theDataView_[row][colPos]) != uDataSet.end())
404 __SS__ <<
"Entries in Unique Data column "
405 << columnsInfo_[colPos].getName()
406 << (
" are not unique. Specifically at row=" +
407 std::to_string(row) +
408 " value=" + theDataView_[row][colPos])
412 uDataSet.insert(theDataView_[row][colPos]);
414 if(uDataSet.size() != getNumberOfRows())
416 __SS__ <<
"Entries in Unique Data column "
417 << columnsInfo_[colPos].getName() <<
" are not unique!"
418 <<
"There are " << getNumberOfRows()
419 <<
" records and the unique data count is " << uDataSet.size()
427 colPos = (
unsigned int)-1;
428 while((colPos =
findColByType(TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA,
429 colPos + 1)) != INVALID)
434 for(
unsigned int groupIdColPos = 0; groupIdColPos < columnsInfo_.size();
436 if(columnsInfo_[groupIdColPos].isGroupID())
438 std::map<std::string ,
439 std::pair<
unsigned int ,
440 std::set<std::string >>>
443 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
447 for(
const auto& groupId : groupIds)
449 uGroupDataSets[groupId].first++;
451 if(uGroupDataSets[groupId].second.find(
452 theDataView_[row][colPos]) !=
453 uGroupDataSets[groupId].second.end())
455 __SS__ <<
"Entries in Unique Group Data column " << colPos
456 <<
":" << columnsInfo_[colPos].getName()
457 <<
" are not unique for group ID '" << groupId
458 <<
".' Specifically at row=" << std::to_string(row)
459 <<
" value=" << theDataView_[row][colPos] << __E__;
462 uGroupDataSets[groupId].second.insert(
463 theDataView_[row][colPos]);
467 for(
const auto& groupPair : uGroupDataSets)
468 if(uGroupDataSets[groupPair.first].second.size() !=
469 uGroupDataSets[groupPair.first].first)
472 <<
"Entries in Unique Data column "
473 << columnsInfo_[colPos].getName()
474 <<
" are not unique for group '" << groupPair.first
476 <<
"There are " << uGroupDataSets[groupPair.first].first
477 <<
" records and the unique data count is "
478 << uGroupDataSets[groupPair.first].second.size() << __E__;
484 auto rowDefaults = initRowDefaults();
491 std::set<std::string> groupIdIndexes, childLinkIndexes, childLinkIdLabels;
492 unsigned int groupIdIndexesCount = 0, childLinkIndexesCount = 0,
493 childLinkIdLabelsCount = 0;
495 std::pair<
unsigned int ,
unsigned int > tmpLinkPair;
498 if(getNumberOfRows() != theDataView_.size())
500 __SS__ <<
"Impossible row mismatch " << getNumberOfRows() <<
" vs "
501 << theDataView_.size() <<
"! How did you get here?" << __E__;
504 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
505 if(getNumberOfColumns() != theDataView_[row].size())
507 __SS__ <<
"Impossible col mismatch " << getNumberOfColumns() <<
" vs ["
508 << row <<
"]" << theDataView_[row].size()
509 <<
"! How did you get here?" << __E__;
512 if(getNumberOfColumns() != columnsInfo_.size())
514 __SS__ <<
"Impossible col info mismatch " << getNumberOfColumns() <<
" vs "
515 << columnsInfo_.size() <<
"! How did you get here?" << __E__;
518 if(getNumberOfColumns() != rowDefaults.size())
520 __SS__ <<
"Impossible col default mismatch " << getNumberOfColumns() <<
" vs "
521 << rowDefaults.size() <<
"! How did you get here?" << __E__;
525 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
527 if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
529 const std::vector<std::string>& theDataChoices =
530 columnsInfo_[col].getDataChoices();
533 if(theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=1")
537 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
541 if(theDataView_[row][col] == rowDefaults[col])
544 for(
const auto& choice : theDataChoices)
546 if(theDataView_[row][col] == choice)
554 __SS__ << getTableName() <<
" Error:\t'" << theDataView_[row][col]
555 <<
"' in column " << columnsInfo_[col].getName()
556 <<
" is not a valid Fixed Choice option. "
557 <<
"Possible values are as follows: ";
559 ss << columnsInfo_[col].getDefaultValue()
560 << (columnsInfo_[col].getDataChoices().size() ?
", " :
"");
561 for(
unsigned int i = 0;
562 i < columnsInfo_[col].getDataChoices().size();
565 if(columnsInfo_[col].getDataChoices()[i] ==
"arbitraryBool=0")
568 if(i && (i != 1 || columnsInfo_[col].getDataChoices()[0] !=
571 ss << columnsInfo_[col].getDataChoices()[i];
578 else if(columnsInfo_[col].isChildLink())
582 const std::vector<std::string>& theDataChoices =
583 columnsInfo_[col].getDataChoices();
586 if(!theDataChoices.size() || theDataChoices[0] ==
"arbitraryBool=1")
591 (theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=0");
595 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
600 for(
const auto& choice : theDataChoices)
602 if(skipOne && !hasSkipped)
608 if(theDataView_[row][col] == choice)
616 __SS__ << getTableName() <<
" Error:\t the value '"
617 << theDataView_[row][col] <<
"' in column "
618 << columnsInfo_[col].getName()
619 <<
" is not a valid Fixed Choice option. "
620 <<
"Possible values are as follows: ";
625 for(
unsigned int i = skipOne ? 1 : 0;
626 i < columnsInfo_[col].getDataChoices().size();
629 if(i > (skipOne ? 1 : 0))
631 ss << columnsInfo_[col].getDataChoices()[i];
638 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_ON_OFF)
639 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
641 if(theDataView_[row][col] ==
"1" ||
642 theDataView_[row][col] ==
"TRUE" ||
643 theDataView_[row][col] ==
"on" || theDataView_[row][col] ==
"On" ||
644 theDataView_[row][col] ==
"ON")
645 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_ON;
646 else if(theDataView_[row][col] ==
"0" ||
647 theDataView_[row][col] ==
"FALSE" ||
648 theDataView_[row][col] ==
"off" ||
649 theDataView_[row][col] ==
"Off" ||
650 theDataView_[row][col] ==
"OFF")
651 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_OFF;
654 __SS__ << getTableName() <<
" Error:\t the value '"
655 << theDataView_[row][col] <<
"' in column "
656 << columnsInfo_[col].getName()
657 <<
" is not a valid Type (On/Off) std::string. Possible "
658 "values are 1, on, On, ON, 0, off, Off, OFF."
663 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_TRUE_FALSE)
664 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
666 if(theDataView_[row][col] ==
"1" ||
667 theDataView_[row][col] ==
"true" ||
668 theDataView_[row][col] ==
"True" ||
669 theDataView_[row][col] ==
"TRUE")
670 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_TRUE;
671 else if(theDataView_[row][col] ==
"0" ||
672 theDataView_[row][col] ==
"false" ||
673 theDataView_[row][col] ==
"False" ||
674 theDataView_[row][col] ==
"FALSE")
675 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_FALSE;
678 __SS__ << getTableName() <<
" Error:\t the value '"
679 << theDataView_[row][col] <<
"' in column "
680 << columnsInfo_[col].getName()
681 <<
" is not a valid Type (True/False) std::string. "
682 "Possible values are 1, true, True, TRUE, 0, false, "
688 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_YES_NO)
689 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
691 if(theDataView_[row][col] ==
"1" ||
692 theDataView_[row][col] ==
"TRUE" ||
693 theDataView_[row][col] ==
"yes" ||
694 theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
695 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_YES;
696 else if(theDataView_[row][col] ==
"0" ||
697 theDataView_[row][col] ==
"FALSE" ||
698 theDataView_[row][col] ==
"no" ||
699 theDataView_[row][col] ==
"No" ||
700 theDataView_[row][col] ==
"NO")
701 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_NO;
704 __SS__ << getTableName() <<
" Error:\t the value '"
705 << theDataView_[row][col] <<
"' in column "
706 << columnsInfo_[col].getName()
707 <<
" is not a valid Type (Yes/No) std::string. Possible "
708 "values are 1, yes, Yes, YES, 0, no, No, NO."
713 else if(columnsInfo_[col].isGroupID())
715 colLinkGroupIDs_[columnsInfo_[col].getChildLinkIndex()] =
718 groupIdIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
719 ++groupIdIndexesCount;
721 else if(columnsInfo_[col].isChildLink())
724 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
725 if(theDataView_[row][col] ==
"NoLink" ||
726 theDataView_[row][col] ==
"No_Link" ||
727 theDataView_[row][col] ==
"NOLINK" ||
728 theDataView_[row][col] ==
"NO_LINK" ||
729 theDataView_[row][col] ==
"Nolink" ||
730 theDataView_[row][col] ==
"nolink" ||
731 theDataView_[row][col] ==
"noLink")
732 theDataView_[row][col] =
733 TableViewColumnInfo::DATATYPE_LINK_DEFAULT;
736 childLinkIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
737 ++childLinkIndexesCount;
740 if(columnsInfo_[col].getDataType() !=
741 TableViewColumnInfo::DATATYPE_STRING)
743 __SS__ << getTableName() <<
" Error:\t"
744 <<
"Column " << col <<
" with name '"
745 << columnsInfo_[col].getName()
746 <<
"' is a Child Link column and has an illegal data type of '"
747 << columnsInfo_[col].getDataType()
748 <<
"'. The data type for Child Link columns must be "
749 << TableViewColumnInfo::DATATYPE_STRING << __E__;
756 else if(columnsInfo_[col].isChildLinkUID() ||
757 columnsInfo_[col].isChildLinkGroupID())
760 childLinkIdLabels.emplace(columnsInfo_[col].getChildLinkIndex());
761 ++childLinkIdLabelsCount;
764 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
765 if(theDataView_[row][col] ==
"")
766 theDataView_[row][col] = rowDefaults[col];
773 if(columnsInfo_[col].isNumberDataType())
775 std::string minimumValueString = columnsInfo_[col].getMinValue();
776 std::string maximumValueString = columnsInfo_[col].getMaxValue();
777 double minimumValue, maximumValue, valueFromTable;
778 bool minExists =
false, maxExists =
false;
780 if(!minimumValueString.empty())
787 __SS__ <<
"Inavlid user spec'd min value '" << minimumValueString
788 <<
"' which is not a valid number. The minimum value must "
789 "be a number (environment variables and math "
790 "operations are allowed)."
796 if(!maximumValueString.empty())
803 __SS__ <<
"Inavlid user spec'd max value '" << maximumValueString
804 <<
"' which is not a valid number. The maximum value must "
805 "be a number (environment variables and math "
806 "operations are allowed)."
812 if(minExists && maxExists && minimumValue > maximumValue)
814 __SS__ <<
"Minimum value is greater than maximum, check table editor "
820 if(minExists || maxExists)
821 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
824 if(minExists && valueFromTable < minimumValue)
827 <<
"The value '" << valueFromTable <<
"'("
830 <<
") at [row,col]=[" << row <<
"," << col
831 <<
"] is outside the established limits: "
833 <<
" is lower than the specified minimum " << minimumValue
837 if(maxExists && valueFromTable > maximumValue)
840 <<
"This value '" << valueFromTable <<
"'("
843 <<
") at [row,col]=[" << row <<
"," << col
844 <<
"] is outside the established limits: "
846 <<
" is greater than the specified maximum "
847 << maximumValue <<
"." << __E__;
855 if(groupIdIndexes.size() != groupIdIndexesCount)
857 __SS__ << (
"GroupId Labels are not unique!") <<
"There are "
858 << groupIdIndexesCount <<
" GroupId Labels and the unique count is "
859 << groupIdIndexes.size() << __E__;
862 if(childLinkIndexes.size() != childLinkIndexesCount)
864 __SS__ << (
"Child Link Labels are not unique!") <<
"There are "
865 << childLinkIndexesCount
866 <<
" Child Link Labels and the unique count is "
867 << childLinkIndexes.size() << __E__;
870 if(childLinkIdLabels.size() != childLinkIdLabelsCount)
872 __SS__ << (
"Child Link ID Labels are not unique!") <<
"There are "
873 << childLinkIdLabelsCount
874 <<
" Child Link ID Labels and the unique count is "
875 << childLinkIdLabels.size() << __E__;
881 __COUTT__ <<
"Error occurred in TableView::init() for version=" << version_
895 bool doConvertEnvironmentVariables)
const
897 if(!(row < getNumberOfRows() && col < theDataView_[row].size()))
899 __SS__ <<
"Invalid row col requested " << row <<
"," << col <<
" vs "
900 << getNumberOfRows() <<
"," << columnsInfo_.size() <<
"/"
901 << theDataView_[row].size() << __E__;
906 theDataView_[row][col], col, doConvertEnvironmentVariables);
916 bool doConvertEnvironmentVariables)
const
918 if(col >= columnsInfo_.size())
920 __SS__ <<
"Invalid col requested" << __E__;
924 if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA &&
926 value == columnsInfo_[col].getDefaultDefaultValue(columnsInfo_[col].getType(),
927 columnsInfo_[col].getDataType()))
931 std::vector<std::string> choices = columnsInfo_[col].getDataChoices();
934 bool skipOne = (choices.size() && choices[0].find(
"arbitraryBool=") == 0);
935 size_t index = (skipOne ? 1 : 0);
936 if(choices.size() > index)
938 return doConvertEnvironmentVariables
944 if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_STRING)
945 return doConvertEnvironmentVariables
948 else if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
951 doConvertEnvironmentVariables
957 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
958 <<
" in configuration " << tableName_
959 <<
" at column=" << columnsInfo_[col].getName()
960 <<
" for getValue with type '"
975 bool doConvertEnvironmentVariables)
const
977 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
979 __SS__ <<
"Invalid row col requested: row=" << row
980 <<
" numRows=" << getNumberOfRows() <<
" col=" << col
981 <<
" numCols=" << columnsInfo_.size() <<
" table=" << tableName_ << __E__;
985 __COUTS__(30) << columnsInfo_[col].getType() <<
" " << col << __E__;
987 if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_ON_OFF)
989 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" ||
990 theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
991 return TableViewColumnInfo::TYPE_VALUE_ON;
993 return TableViewColumnInfo::TYPE_VALUE_OFF;
995 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_TRUE_FALSE)
997 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" ||
998 theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
999 return TableViewColumnInfo::TYPE_VALUE_TRUE;
1001 return TableViewColumnInfo::TYPE_VALUE_FALSE;
1003 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_YES_NO)
1005 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" ||
1006 theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
1007 return TableViewColumnInfo::TYPE_VALUE_YES;
1009 return TableViewColumnInfo::TYPE_VALUE_NO;
1012 return doConvertEnvironmentVariables
1014 : theDataView_[row][col];
1027 bool doConvertEnvironmentVariables ,
1028 bool quotesToDoubleQuotes )
const
1030 std::string val =
getValueAsString(row, col, doConvertEnvironmentVariables);
1031 std::string retVal =
"";
1032 retVal.reserve(val.size());
1033 for(
unsigned int i = 0; i < val.size(); ++i)
1037 else if(val[i] ==
'\t')
1039 else if(val[i] ==
'\r')
1046 if(quotesToDoubleQuotes && val[i] ==
'"')
1048 else if(!quotesToDoubleQuotes && val[i] ==
'"')
1061 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
1063 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
1067 if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_STRING)
1068 theDataView_[row][col] = value;
1072 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
1073 <<
" in configuration " << tableName_
1074 <<
" at column=" << columnsInfo_[col].getName()
1075 <<
" for setValue with type '"
1084 setValue(std::string(value), row, col);
1094 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
1096 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
1100 theDataView_[row][col] = value;
1113 std::string baseValueAsString ,
1114 bool doMathAppendStrategy ,
1115 std::string childLinkIndex ,
1116 std::string groupId )
1118 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
1120 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
1124 bool isUniqueGroupCol =
1125 (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA);
1126 unsigned int childLinkIndexCol = -1;
1127 if(isUniqueGroupCol)
1129 __COUTVS__(12, childLinkIndex);
1130 __COUTVS__(12, groupId);
1132 __COUTVS__(12, childLinkIndexCol);
1135 __COUTT__ <<
"Current '" << columnsInfo_[col].getName() <<
"' "
1136 << (isUniqueGroupCol ?
"(Unique in Group) " :
"")
1137 <<
"unique data entry is data[" << row <<
"][" << col <<
"] = '"
1138 << theDataView_[row][col] <<
"' baseValueAsString = " << baseValueAsString
1139 <<
" doMathAppendStrategy = " << doMathAppendStrategy << __E__;
1141 bool firstConflict =
true;
1142 int maxUniqueData = -1;
1143 std::string tmpString =
"";
1146 std::string numString;
1147 std::string opString;
1153 for(
unsigned int r = 0; r < getNumberOfRows(); ++r)
1158 if(isUniqueGroupCol && !isEntryInGroupCol(r, childLinkIndexCol, groupId))
1164 tmpString = theDataView_[r][col];
1166 __COUTS__(3) <<
"row[" << r <<
"] tmpString " << tmpString << __E__;
1168 for(index = tmpString.length() - 1; index < tmpString.length(); --index)
1170 __COUTS__(3) << index <<
" tmpString[index] " << tmpString[index] << __E__;
1171 if(!(tmpString[index] >=
'0' && tmpString[index] <=
'9'))
1176 __COUTS__(3) <<
"index " << index <<
" foundAny " << foundAny << __E__;
1178 if(tmpString.length() && foundAny)
1181 numString = tmpString.substr(index + 1);
1184 tmpString = tmpString.substr(0, index + 1);
1186 if(doMathAppendStrategy && tmpString.size())
1190 for(index = tmpString.length() - 1; index < tmpString.length(); --index)
1193 << index <<
" tmpString[index] " << tmpString[index] << __E__;
1194 if(!(tmpString[index] ==
'+' || tmpString[index] ==
' '))
1202 opString = tmpString.substr(index + 1);
1205 tmpString = tmpString.substr(0, index + 1);
1209 __COUTS__(3) << tmpString <<
" vs " << baseValueAsString << __E__;
1211 if(baseValueAsString !=
"" && tmpString != baseValueAsString)
1214 __COUTS__(3) <<
"Found unique data base string '" << tmpString
1215 <<
"' and number string '" << numString <<
"' in last record '"
1216 << theDataView_[r][col] <<
"'" << __E__;
1221 if(baseValueAsString.size() &&
1222 baseValueAsString[baseValueAsString.size() - 1] >=
'0' &&
1223 baseValueAsString[baseValueAsString.size() - 1] <=
'9')
1224 baseValueAsString +=
'_';
1226 firstConflict =
false;
1230 sscanf(numString.c_str(),
"%u", &index);
1232 if((
int)index > maxUniqueData)
1234 maxUniqueData = (int)index;
1236 if(baseValueAsString ==
"")
1237 baseValueAsString = tmpString;
1240 else if(maxUniqueData < 0 &&
1241 (baseValueAsString ==
"" || tmpString == baseValueAsString))
1246 if(baseValueAsString.size() &&
1247 baseValueAsString[baseValueAsString.size() - 1] >=
'0' &&
1248 baseValueAsString[baseValueAsString.size() - 1] <=
'9')
1249 baseValueAsString +=
'_';
1251 firstConflict =
false;
1258 __COUTVS__(12, maxUniqueData);
1259 __COUTVS__(12, baseValueAsString);
1261 if(maxUniqueData == -1)
1263 if(baseValueAsString !=
"")
1264 theDataView_[row][col] = baseValueAsString;
1266 theDataView_[row][col] = columnsInfo_[col].getDefaultValue();
1272 char indexString[1000];
1273 sprintf(indexString,
"%u", maxUniqueData);
1275 __COUTVS__(12, indexString);
1276 __COUTVS__(12, baseValueAsString);
1278 if(doMathAppendStrategy)
1279 theDataView_[row][col] = baseValueAsString +
" + " + indexString;
1281 theDataView_[row][col] = baseValueAsString + indexString;
1284 __COUTT__ <<
"New unique data entry is data[" << row <<
"][" << col <<
"] = '"
1285 << theDataView_[row][col] <<
"'" << __E__;
1289 std::stringstream ss;
1291 __COUT_MULTI__(13, ss.str());
1294 return theDataView_[row][col];
1300 unsigned int TableView::initColUID(
void)
1302 if(colUID_ != INVALID)
1307 if(colUID_ == INVALID)
1309 __COUT__ <<
"Column Types: " << __E__;
1310 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1311 std::cout << columnsInfo_[col].getType() <<
"() "
1312 << columnsInfo_[col].getName() << __E__;
1313 __SS__ <<
"\tMissing UID Column in table named '" << tableName_ <<
"'" << __E__;
1324 if(colUID_ != INVALID)
1327 __COUT__ <<
"Column Types: " << __E__;
1328 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1329 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1332 __SS__ << (
"Missing UID Column in config named " + tableName_ +
1333 ". (Possibly TableView was just not initialized?" +
1334 " This is the const call so can not alter class members)")
1345 unsigned int TableView::initColStatus(
void)
1347 if(colStatus_ != INVALID)
1351 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1352 if(columnsInfo_[col].getName() == TableViewColumnInfo::COL_NAME_STATUS)
1357 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1358 if(columnsInfo_[col].getName() == TableViewColumnInfo::COL_NAME_ENABLED)
1366 __SS__ <<
"\tMissing column named '" << TableViewColumnInfo::COL_NAME_STATUS
1367 <<
"' or '" << TableViewColumnInfo::COL_NAME_ENABLED <<
"' in table '"
1368 << tableName_ <<
".'" << __E__;
1369 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1370 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1371 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1381 unsigned int TableView::initColPriority(
void)
1383 if(colPriority_ != INVALID)
1384 return colPriority_;
1388 findCol(
"*" + TableViewColumnInfo::COL_NAME_PRIORITY);
1389 if(colPriority_ == INVALID)
1391 __SS__ <<
"\tMissing column named '" << TableViewColumnInfo::COL_NAME_PRIORITY
1392 <<
"' in table '" << tableName_ <<
".'" << __E__;
1393 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1394 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1395 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1400 return colPriority_;
1409 if(colStatus_ != INVALID)
1412 __SS__ <<
"\tMissing column named '" << TableViewColumnInfo::COL_NAME_STATUS
1413 <<
"' or '" << TableViewColumnInfo::COL_NAME_ENABLED <<
"' in table '"
1414 << tableName_ <<
".'"
1415 <<
" (The Status column is identified when the TableView is initialized)"
1418 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1419 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1420 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1427 __COUTT__ << ss.str();
1440 if(colPriority_ != INVALID)
1441 return colPriority_;
1443 __SS__ <<
"Priority column was not found... \nColumn Types: " << __E__;
1445 ss <<
"Missing " << TableViewColumnInfo::COL_NAME_PRIORITY
1446 <<
" Column in table named '" << tableName_
1447 <<
".' (The Priority column is identified when the TableView is initialized)"
1451 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1452 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1453 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1466 const unsigned int& col,
1467 const std::string& groupID)
1470 if(isEntryInGroupCol(row, col, groupID))
1472 __SS__ <<
"GroupID (" << groupID <<
") added to row (" << row
1473 <<
" is already present!" << __E__;
1482 if(getDataView()[row][col] ==
"" ||
1483 getDataView()[row][col] == getDefaultRowValues()[col])
1486 setValue(groupID +
" | " + getDataView()[row][col], row, col);
1498 const unsigned int groupIdCol,
1499 const std::string& groupID,
1500 bool onlyStatusTrue ,
1501 bool orderedByPriority )
const
1503 std::vector<
unsigned int > retVector;
1504 std::vector<std::vector<
unsigned int >> groupRowVectors =
1505 getGroupRowsInVectors(groupIdCol, groupID, onlyStatusTrue, orderedByPriority);
1507 for(
const auto& groupRowVector : groupRowVectors)
1508 for(
const auto& groupRow : groupRowVector)
1509 retVector.push_back(groupRow);
1521 const unsigned int groupIdCol,
1522 const std::string& groupID,
1523 bool onlyStatusTrue )
const
1525 return getGroupRowsInVectors(
1526 groupIdCol, groupID, onlyStatusTrue,
true );
1537 std::vector<std::vector<
unsigned int >> TableView::getGroupRowsInVectors(
1538 const unsigned int groupIdCol,
1539 const std::string& groupID,
1540 bool onlyStatusTrue,
1541 bool orderedByPriority)
const
1543 std::map<uint64_t , std::vector<
unsigned int >>
1545 std::vector<std::vector<
unsigned int >> retVector;
1546 uint64_t tmpPriority;
1549 if(!(orderedByPriority &&
1550 colPriority_ != INVALID))
1551 retVector.push_back(std::vector<unsigned int /*group row*/>());
1553 __COUTS__(2) <<
"getGroupRowsInVectors: " << groupID <<
" at col " << groupIdCol
1555 for(
unsigned int r = 0; r < getNumberOfRows(); ++r)
1556 if(groupID ==
"" || groupID ==
"*" || groupIdCol == INVALID ||
1557 isEntryInGroupCol(r, groupIdCol, groupID))
1559 if(groupIdCol != INVALID)
1560 __COUTS__(2) <<
"Row " << r <<
" '" << getDataView()[r][groupIdCol]
1561 <<
"' is in group " << groupID << __E__;
1563 if(onlyStatusTrue && colStatus_ != INVALID)
1565 getValue(tmpStatus, r, colStatus_);
1571 if(orderedByPriority && colPriority_ != INVALID)
1573 getValue(tmpPriority, r, colPriority_);
1575 mapByPriority[tmpPriority ? tmpPriority : 100].push_back(r);
1578 retVector[0].push_back(r);
1581 __COUTS__(2) <<
"Row " << r <<
" '" << getDataView()[r][groupIdCol]
1582 <<
"' is NOT in group " << groupID << __E__;
1584 if(orderedByPriority && colPriority_ != INVALID)
1588 for(
const auto& priorityChildRowVector : mapByPriority)
1590 retVector.push_back(std::vector<unsigned int /*group row*/>());
1591 for(
const auto& priorityChildRow : priorityChildRowVector.second)
1592 retVector[retVector.size() - 1].push_back(priorityChildRow);
1595 __COUT__ <<
"Returning priority children list." << __E__;
1608 const unsigned int& col,
1609 const std::string& groupNeedle,
1610 bool deleteRowIfNoGroupLeft)
1612 __COUT__ <<
"removeRowFromGroup groupNeedle " << groupNeedle << __E__;
1613 std::set<std::string> groupIDList;
1614 if(!isEntryInGroupCol(row, col, groupNeedle, &groupIDList))
1617 <<
"GroupID (" << groupNeedle <<
") removed from row (" << row
1618 <<
") was already removed! Is there a strange GroupID wildcard match issue? {"
1628 std::string newValue =
"";
1629 unsigned int cnt = 0;
1630 for(
const auto& groupID : groupIDList)
1632 __COUTT__ << groupID <<
" " << groupNeedle <<
" " << newValue << __E__;
1633 if(groupID == groupNeedle)
1638 newValue += groupID;
1641 bool wasDeleted =
false;
1642 if(deleteRowIfNoGroupLeft && newValue ==
"")
1644 __COUTT__ <<
"Delete row since it no longer part of any group." << __E__;
1651 __COUTT__ << getDataView()[row][col] << __E__;
1664 const std::string& childLinkIndex,
1665 const std::string& groupNeedle)
const
1669 return isEntryInGroupCol(r, c, groupNeedle);
1681 bool TableView::isEntryInGroupCol(
const unsigned int& r,
1682 const unsigned int& c,
1683 const std::string& groupNeedle,
1684 std::set<std::string>* groupIDList)
const
1686 if(r >= getNumberOfRows() || c >= getNumberOfColumns())
1688 __SS__ <<
"Invalid row/col requested!" << __E__;
1697 __COUTS__(2) <<
"groupNeedle " << groupNeedle << __E__;
1700 for(; j < theDataView_[r][c].size(); ++j)
1701 if((theDataView_[r][c][j] ==
' ' ||
1702 theDataView_[r][c][j] ==
'|') &&
1705 else if((theDataView_[r][c][j] ==
1707 theDataView_[r][c][j] ==
'|') &&
1711 groupIDList->emplace(theDataView_[r][c].substr(i, j - i));
1713 __COUTS__(2) <<
"Group found to compare: "
1714 << theDataView_[r][c].substr(i, j - i) << __E__;
1715 if(groupIDList ? groupNeedle == theDataView_[r][c].substr(i, j - i)
1717 theDataView_[r][c].substr(i, j - i), groupNeedle))
1719 __COUTS__(2) <<
"'" << theDataView_[r][c].substr(i, j - i)
1720 <<
"' is in group '" << groupNeedle <<
"'!" << __E__;
1732 groupIDList->emplace(theDataView_[r][c].substr(i, j - i));
1734 __COUTS__(2) <<
"Group found to compare: " << theDataView_[r][c].substr(i, j - i)
1736 if(groupIDList ? groupNeedle == theDataView_[r][c].substr(i, j - i)
1740 __COUTS__(2) <<
"'" << theDataView_[r][c].substr(i, j - i)
1741 <<
"' is in group '" << groupNeedle <<
"'!" << __E__;
1758 unsigned int r)
const
1763 unsigned int r)
const
1767 std::set<std::string> retSet;
1772 if(r != (
unsigned int)-1)
1774 if(r >= getNumberOfRows())
1776 __SS__ <<
"Invalid row requested!" << __E__;
1808 for(r = 0; r < getNumberOfRows(); ++r)
1860 if(!childLinkIndex.size())
1862 __SS__ <<
"Empty childLinkIndex string parameter!" << __E__;
1867 const char* needleChildLinkIndex = &childLinkIndex[0];
1871 size_t spacePos = childLinkIndex.find(
' ');
1872 if(spacePos != std::string::npos &&
1873 spacePos + 1 < childLinkIndex.size())
1876 needleChildLinkIndex = &childLinkIndex[spacePos + 1];
1879 std::map<std::string, unsigned int>::const_iterator it =
1880 colLinkGroupIDs_.find(needleChildLinkIndex);
1882 colLinkGroupIDs_.end())
1886 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1889 if(columnsInfo_[col].isChildLink() || columnsInfo_[col].isChildLinkUID() ||
1890 columnsInfo_[col].isChildLinkGroupID() || columnsInfo_[col].isGroupID())
1892 if(needleChildLinkIndex == columnsInfo_[col].getChildLinkIndex())
1898 <<
"Error! Incompatible table for this group link! Table '" << tableName_
1899 <<
"' is missing a GroupID column with data type '"
1900 << TableViewColumnInfo::TYPE_START_GROUP_ID <<
"-" << needleChildLinkIndex
1902 <<
"Note: you can separate the child GroupID column data type from "
1903 <<
"the parent GroupLink column data type; this is accomplished by using a space "
1904 <<
"character at the parent level - the string after the space will be treated "
1906 <<
"child GroupID column data type." << __E__;
1907 ss <<
"Existing Column GroupIDs: " << __E__;
1908 for(
auto& groupIdColPair : colLinkGroupIDs_)
1909 ss <<
"\t" << groupIdColPair.first <<
" : col-" << groupIdColPair.second << __E__;
1911 ss <<
"Existing Column Types: " << __E__;
1912 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1913 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1923 const std::string& value,
1924 unsigned int offsetRow,
1925 bool doNotThrow )
const
1927 for(
unsigned int row = offsetRow; row < theDataView_.size(); ++row)
1929 if(theDataView_[row][col] == value)
1933 return TableView::INVALID;
1935 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find value=" << value
1936 <<
" in column named " << columnsInfo_[col].getName()
1937 <<
" with type=" << columnsInfo_[col].getType() << __E__ << __E__
1948 const std::string& value,
1949 const std::string& groupId,
1950 const std::string& childLinkIndex,
1951 unsigned int offsetRow)
const
1954 for(
unsigned int row = offsetRow; row < theDataView_.size(); ++row)
1956 if(theDataView_[row][col] == value && isEntryInGroupCol(row, groupIdCol, groupId))
1960 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find in group the value=" << value
1961 <<
" in column named '" << columnsInfo_[col].getName()
1962 <<
"' with type=" << columnsInfo_[col].getType() <<
" and GroupID: '"
1963 << groupId <<
"' in column '" << groupIdCol
1964 <<
"' with GroupID child link index '" << childLinkIndex <<
"'" << __E__;
1975 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1977 columnsInfo_[col].getName() ))
1980 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find column named '" << wildCardName
1982 ss <<
"Existing columns:\n";
1983 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1984 ss <<
"\t" << columnsInfo_[col].getName() <<
"\n";
1997 unsigned int startingCol)
const
1999 for(
unsigned int col = startingCol; col < columnsInfo_.size(); ++col)
2001 __COUTS__(40) << columnsInfo_[col].getType() << __E__;
2002 if(columnsInfo_[col].getType() == type)
2016 if(!getNumberOfRows())
2017 return getNumberOfColumns();
2018 return theDataView_[0].size();
2022 std::set<std::string> TableView::getColumnNames(
void)
const
2024 std::set<std::string> retSet;
2025 for(
auto& colInfo : columnsInfo_)
2026 retSet.emplace(colInfo.getName());
2031 std::map<std::string,
unsigned int > TableView::getColumnNamesMap(
void)
const
2033 std::map<std::string,
unsigned int > retMap;
2035 for(
auto& colInfo : columnsInfo_)
2036 retMap.emplace(std::make_pair(colInfo.getName(), c++));
2041 std::set<std::string> TableView::getColumnStorageNames(
void)
const
2043 std::set<std::string> retSet;
2044 for(
auto& colInfo : columnsInfo_)
2045 retSet.emplace(colInfo.getStorageName());
2050 const std::vector<std::string>& TableView::initRowDefaults(
void)
2052 std::vector<std::string>& retVec = rowDefaultValues_;
2056 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
2063 if(columnsInfo_[col].isChildLink())
2065 const std::vector<std::string>& theDataChoices =
2066 columnsInfo_[col].getDataChoices();
2069 if(!theDataChoices.size() ||
2070 theDataChoices[0] ==
"arbitraryBool=1")
2071 retVec.push_back(columnsInfo_[col].getDefaultValue());
2075 (theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=0");
2080 bool foundDefault =
false;
2082 for(
const auto& choice : theDataChoices)
2083 if(skipOne && !hasSkipped)
2088 else if(choice == columnsInfo_[col].getDefaultValue())
2090 foundDefault =
true;
2095 if(!foundDefault && theDataChoices.size() > (skipOne ? 1 : 0))
2096 retVec.push_back(theDataChoices[(skipOne ? 1 : 0)]);
2098 retVec.push_back(columnsInfo_[col].getDefaultValue());
2102 retVec.push_back(columnsInfo_[col].getDefaultValue());
2107 return rowDefaultValues_;
2113 if(column >= columnsInfo_.size())
2115 __SS__ <<
"\nCan't find column " << column
2116 <<
"\n\n\n\nThe column info is likely missing due to incomplete "
2117 "Configuration View filling.\n\n"
2122 return columnsInfo_[column];
2134 void TableView::setAuthor(
const std::string& author) { author_ = author; }
2137 void TableView::setCreationTime(time_t t) { creationTime_ = t; }
2140 void TableView::setLastAccessTime(time_t t) { lastAccessTime_ = t; }
2143 void TableView::setLooseColumnMatching(
bool setValue)
2145 fillWithLooseColumnMatching_ =
setValue;
2149 void TableView::doGetSourceRawData(
bool setValue) { getSourceRawData_ =
setValue; }
2152 void TableView::reset(
void)
2157 columnsInfo_.clear();
2158 theDataView_.clear();
2162 void TableView::print(std::ostream& out )
const
2164 out <<
"============================================================================="
2167 out <<
"Print: " << tableName_ <<
" Version: " << version_ <<
" Comment: " << comment_
2168 <<
" Author: " << author_ <<
" Creation Time: " << ctime(&creationTime_) << __E__;
2169 out <<
"\t\tNumber of Cols " << getNumberOfColumns() << __E__;
2170 out <<
"\t\tNumber of Rows " << getNumberOfRows() << __E__;
2172 out <<
"Columns:\t";
2173 for(
int i = 0; i < (int)columnsInfo_.size(); ++i)
2174 out << i <<
":" << columnsInfo_[i].getName() <<
":"
2175 << columnsInfo_[i].getStorageName() <<
":" << columnsInfo_[i].getType() <<
":"
2176 << columnsInfo_[i].getDataType() <<
"\t ";
2179 out <<
"Rows:" << __E__;
2182 for(
int r = 0; r < (int)getNumberOfRows(); ++r)
2184 out << (int)r <<
":\t";
2185 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
2187 out << (int)c <<
":";
2190 if(columnsInfo_[c].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
2192 int choiceIndex = -1;
2193 std::vector<std::string> choices = columnsInfo_[c].getDataChoices();
2196 if(val == columnsInfo_[c].getDefaultValue())
2200 for(
int i = 0; i < (int)choices.size(); ++i)
2201 if(val == choices[i])
2202 choiceIndex = i + 1;
2205 out <<
"ChoiceIndex=" << choiceIndex <<
":";
2208 out << theDataView_[r][c];
2228 void TableView::printJSON(std::ostream& out )
const
2231 std::string tmpCachePrepend = TableBase::GROUP_CACHE_PREPEND;
2233 std::string tmpJsonDocPrepend = TableBase::JSON_DOC_PREPEND;
2235 __COUTS__(32) <<
" '" << tableName_ <<
"' vs " << tmpCachePrepend <<
" or "
2236 << tmpJsonDocPrepend << __E__;
2238 if(tableName_.substr(0, tmpCachePrepend.length()) == tmpCachePrepend ||
2239 tableName_.substr(0, tmpJsonDocPrepend.length()) == tmpJsonDocPrepend)
2247 out <<
"\"NAME\" : \"" << tableName_ <<
"\",\n";
2251 out <<
"\"COMMENT\" : ";
2257 for(
unsigned int i = 0; i < val.size(); ++i)
2261 else if(val[i] ==
'\t')
2263 else if(val[i] ==
'\r')
2268 if(val[i] ==
'"' || val[i] ==
'\\')
2275 out <<
"\"AUTHOR\" : \"" << author_ <<
"\",\n";
2276 out <<
"\"CREATION_TIME\" : " << creationTime_ <<
",\n";
2281 out <<
"\"COL_TYPES\" : {\n";
2282 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
2284 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
2285 out <<
"\"" << columnsInfo_[c].getDataType() <<
"\"";
2286 if(c + 1 < (
int)getNumberOfColumns())
2292 out <<
"\"DATA_SET\" : [\n";
2294 for(
int r = 0; r < (int)getNumberOfRows(); ++r)
2297 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
2299 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
2304 if(c + 1 < (
int)getNumberOfColumns())
2309 if(r + 1 < (
int)getNumberOfRows())
2319 void TableView::printCSV(std::ostream& out ,
2320 const std::string& valueDelimeter ,
2321 const std::string& recordDelimeter ,
2322 bool includeColumnNames )
const
2325 std::string tmpCachePrepend = TableBase::GROUP_CACHE_PREPEND;
2327 std::string tmpJsonDocPrepend = TableBase::JSON_DOC_PREPEND;
2329 __COUTS__(32) <<
" '" << tableName_ <<
"' vs " << tmpCachePrepend <<
" or "
2330 << tmpJsonDocPrepend << __E__;
2332 if(tableName_.substr(0, tmpCachePrepend.length()) == tmpCachePrepend ||
2333 tableName_.substr(0, tmpJsonDocPrepend.length()) == tmpJsonDocPrepend)
2335 __SS__ <<
"Cannot convert custom storage data to CSV!" << __E__;
2342 for(
int c = 0; includeColumnNames && c < (int)getNumberOfColumns(); ++c)
2345 out << valueDelimeter;
2346 out <<
"\"" << columnsInfo_[c].getStorageName() <<
"\"";
2348 if(includeColumnNames)
2349 out << recordDelimeter;
2351 for(
int r = 0; r < (int)getNumberOfRows(); ++r)
2353 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
2356 out << valueDelimeter;
2361 out << recordDelimeter;
2377 std::string tmpCachePrepend = TableBase::GROUP_CACHE_PREPEND;
2379 std::string tmpJsonDocPrepend = TableBase::JSON_DOC_PREPEND;
2383 if(tableName_.substr(0, tmpJsonDocPrepend.length()) == tmpJsonDocPrepend ||
2384 tableName_.substr(0, tmpCachePrepend.length()) == tmpCachePrepend)
2386 __COUTS__(3) <<
"Special JSON doc: " << json << __E__;
2393 bool rawData = getSourceRawData_;
2394 if(getSourceRawData_)
2396 __COUTV__(getSourceRawData_);
2397 getSourceRawData_ =
false;
2398 sourceRawData_ =
"";
2401 std::map<std::string ,
unsigned int > keyEntryCountMap;
2402 std::vector<std::string> keys;
2403 keys.push_back(
"NAME");
2404 keys.push_back(
"COMMENT");
2405 keys.push_back(
"AUTHOR");
2406 keys.push_back(
"CREATION_TIME");
2408 keys.push_back(
"DATA_SET");
2412 CV_JSON_FILL_COMMENT,
2413 CV_JSON_FILL_AUTHOR,
2414 CV_JSON_FILL_CREATION_TIME,
2416 CV_JSON_FILL_DATA_SET
2421 __COUTV__(tableName_);
2422 __COUTTV__(getNumberOfRows());
2426 sourceColumnMismatchCount_ = 0;
2427 sourceColumnMissingCount_ = 0;
2428 sourceColumnNames_.clear();
2429 unsigned int colFoundCount = 0;
2431 unsigned int row = -1;
2432 unsigned int colSpeedup = 0;
2433 unsigned int startString, startNumber = 0, endNumber = -1;
2434 unsigned int bracketCount = 0;
2435 unsigned int sqBracketCount = 0;
2440 bool keyIsMatch, keyIsComment;
2441 unsigned int keyIsMatchIndex, keyIsMatchStorageIndex, keyIsMatchCommentIndex;
2442 const std::string COMMENT_ALT_KEY =
"COMMENT";
2444 std::string extractedString =
"", currKey =
"", currVal =
"";
2445 unsigned int currDepth = 0;
2447 std::vector<std::string> jsonPath;
2448 std::vector<char> jsonPathType;
2449 char lastPopType =
'_';
2451 unsigned int matchedKey = -1;
2452 unsigned int lastCol = -1;
2455 for(; i < json.size(); ++i)
2460 if(i - 1 < json.size() &&
2461 json[i - 1] ==
'\\')
2464 inQuotes = !inQuotes;
2470 json.substr(startString + 1, i - startString - 1));
2479 if(jsonPathType[jsonPathType.size() - 1] !=
'{' ||
2482 __COUT__ <<
"Invalid ':' position" << __E__;
2487 jsonPathType.push_back(
'K');
2488 jsonPath.push_back(extractedString);
2507 if(lastPopType ==
'{')
2510 if(jsonPathType[jsonPathType.size() - 1] ==
'K')
2513 jsonPath.pop_back();
2514 jsonPathType.pop_back();
2520 currVal = extractedString;
2523 if(endNumber == (
unsigned int)-1 ||
2524 endNumber <= startNumber)
2527 if(endNumber <= startNumber)
2530 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
2533 currDepth = bracketCount;
2535 if(jsonPathType[jsonPathType.size() - 1] ==
'K')
2537 currKey = jsonPath[jsonPathType.size() - 1];
2542 jsonPath.pop_back();
2543 jsonPathType.pop_back();
2545 else if(jsonPathType[jsonPathType.size() - 1] ==
2549 for(
unsigned int k = jsonPathType.size() - 2; k < jsonPathType.size();
2551 if(jsonPathType[k] ==
'K')
2553 currKey = jsonPath[k];
2558 __COUT__ <<
"Invalid array position" << __E__;
2567 __COUT__ <<
"Invalid ',' position" << __E__;
2578 jsonPathType.push_back(
'{');
2579 jsonPath.push_back(
"{");
2592 if(lastPopType !=
'{' &&
2593 jsonPathType[jsonPathType.size() - 1] ==
'K')
2595 currDepth = bracketCount;
2596 currKey = jsonPath[jsonPathType.size() - 1];
2598 currVal = extractedString;
2601 if(endNumber == (
unsigned int)-1 ||
2602 endNumber <= startNumber)
2605 if(endNumber <= startNumber)
2609 json.substr(startNumber + 1, endNumber - startNumber - 1);
2613 jsonPath.pop_back();
2614 jsonPathType.pop_back();
2617 if(jsonPathType[jsonPathType.size() - 1] !=
'{')
2619 __COUT__ <<
"Invalid '}' position" << __E__;
2623 jsonPath.pop_back();
2624 jsonPathType.pop_back();
2630 jsonPathType.push_back(
'[');
2631 jsonPath.push_back(
"[");
2640 if(jsonPathType[jsonPathType.size() - 1] !=
'[')
2642 __COUT__ <<
"Invalid ']' position" << __E__;
2646 currDepth = bracketCount;
2650 currVal = extractedString;
2653 if(endNumber == (
unsigned int)-1 ||
2654 endNumber <= startNumber)
2657 if(endNumber <= startNumber)
2660 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
2665 for(
unsigned int k = jsonPathType.size() - 2; k < jsonPathType.size(); --k)
2666 if(jsonPathType[k] ==
'K')
2668 currKey = jsonPath[k];
2673 __COUT__ <<
"Invalid array position" << __E__;
2678 if(jsonPathType[jsonPathType.size() - 1] !=
'[')
2680 __COUT__ <<
"Invalid ']' position" << __E__;
2684 jsonPath.pop_back();
2685 jsonPathType.pop_back();
2694 if(startNumber != (
unsigned int)-1 && endNumber == (
unsigned int)-1)
2708 std::cout << i <<
":\t" << json[i] <<
" - ";
2718 std::cout <<
"ExtKey=";
2719 for(
unsigned int k = 0; k < jsonPath.size(); ++k)
2720 std::cout << jsonPath[k] <<
"/";
2722 std::cout << lastPopType <<
" ";
2723 std::cout << bracketCount <<
" ";
2724 std::cout << sqBracketCount <<
" ";
2725 std::cout << inQuotes <<
" ";
2726 std::cout << newValue <<
"-";
2727 std::cout << currKey <<
"-{" << currDepth <<
"}:";
2728 std::cout << currVal <<
" ";
2729 std::cout << startNumber <<
"-";
2730 std::cout << endNumber <<
" ";
2732 __COUTTV__(fillWithLooseColumnMatching_);
2733 __COUTTV__(getNumberOfRows());
2742 for(
unsigned int k = 0; k < keys.size(); ++k)
2743 if((currDepth == 1 && keys[k] == currKey) ||
2744 (currDepth > 1 && keys[k] == jsonPath[1]))
2753 if(matchedKey == CV_JSON_FILL_COMMENT)
2754 setComment(currVal);
2755 else if(matchedKey == CV_JSON_FILL_AUTHOR)
2757 else if(matchedKey == CV_JSON_FILL_CREATION_TIME)
2758 setCreationTime(strtol(currVal.c_str(), 0, 10));
2760 else if(currDepth == 2)
2763 sourceRawData_ += StringMacros::encodeURIComponent(currKey) +
"," +
2764 StringMacros::encodeURIComponent(currVal) +
",";
2765 sourceColumnNames_.emplace(currKey);
2768 else if(matchedKey != (
unsigned int)-1)
2771 __COUTT__ <<
"New Data for:: key[" << matchedKey <<
"]-"
2772 << keys[matchedKey] <<
"\n";
2776 case CV_JSON_FILL_NAME:
2782 if(currVal != getTableName() &&
2784 "TABLE_GROUP_METADATA")
2785 __COUT_WARN__ <<
"JSON-fill Table name mismatch: " << currVal
2786 <<
" vs " << getTableName() << __E__;
2789 case CV_JSON_FILL_COMMENT:
2791 setComment(currVal);
2793 case CV_JSON_FILL_AUTHOR:
2797 case CV_JSON_FILL_CREATION_TIME:
2799 setCreationTime(strtol(currVal.c_str(), 0, 10));
2804 case CV_JSON_FILL_DATA_SET:
2806 __COUTT__ <<
"CV_JSON_FILL_DATA_SET New Data for::" << matchedKey
2807 <<
"]-" << keys[matchedKey] <<
"/" << currDepth
2808 <<
".../" << currKey <<
"\n";
2814 unsigned int col, ccnt = 0;
2815 unsigned int noc = getNumberOfColumns();
2816 for(; ccnt < noc; ++ccnt)
2822 if(fillWithLooseColumnMatching_)
2835 if(getNumberOfRows() == 1)
2836 sourceColumnNames_.emplace(currKey);
2840 if(row >= getNumberOfRows())
2842 __SS__ <<
"Invalid row"
2844 std::cout << ss.str();
2849 theDataView_[row][col] =
2857 col = (ccnt + colSpeedup) % noc;
2863 keyIsComment =
true;
2864 for(keyIsMatchIndex = 0,
2865 keyIsMatchStorageIndex = 0,
2866 keyIsMatchCommentIndex = 0;
2867 keyIsMatchIndex < currKey.size();
2870 if(columnsInfo_[col]
2871 .getStorageName()[keyIsMatchStorageIndex] ==
2873 ++keyIsMatchStorageIndex;
2875 if(currKey[keyIsMatchIndex] ==
'_')
2879 if(keyIsMatchStorageIndex >=
2880 columnsInfo_[col].getStorageName().size() ||
2881 currKey[keyIsMatchIndex] !=
2883 .getStorageName()[keyIsMatchStorageIndex])
2893 keyIsMatchCommentIndex < COMMENT_ALT_KEY.size())
2895 if(currKey[keyIsMatchIndex] !=
2896 COMMENT_ALT_KEY[keyIsMatchCommentIndex])
2899 keyIsComment =
false;
2903 ++keyIsMatchStorageIndex;
2908 __COUTTV__(keyIsMatch);
2909 __COUTTV__(keyIsComment);
2910 __COUTTV__(currKey);
2911 __COUTTV__(columnsInfo_[col].getStorageName());
2912 __COUTTV__(getNumberOfRows());
2915 if(keyIsMatch || keyIsComment)
2918 if(keyEntryCountMap.find(currKey) ==
2919 keyEntryCountMap.end())
2920 keyEntryCountMap[currKey] =
2923 ++keyEntryCountMap.at(currKey);
2926 if(keyEntryCountMap.size() == 1 ||
2927 (keyEntryCountMap.at(currKey) &&
2928 keyEntryCountMap.at(currKey) >
2931 if(getNumberOfRows())
2932 sourceColumnMissingCount_ +=
2933 getNumberOfColumns() - colFoundCount;
2941 if(getNumberOfRows() == 1)
2942 sourceColumnNames_.emplace(currKey);
2946 if(row >= getNumberOfRows())
2948 __SS__ <<
"Invalid row"
2950 __COUT__ <<
"\n" << ss.str();
2955 theDataView_[row][col] = currVal;
2961 if(ccnt >= getNumberOfColumns())
2964 <<
"Invalid column in JSON source data: " << currKey
2965 <<
" not found in column names of table named "
2966 << getTableName() <<
"."
2971 ++sourceColumnMismatchCount_;
2972 if(getNumberOfRows() ==
2974 sourceColumnNames_.emplace(currKey);
2977 __COUT_WARN__ <<
"Trying to ignore error, and not populating "
2982 colSpeedup = (colSpeedup + 1) % noc;
3001 __COUTTV__(fillWithLooseColumnMatching_);
3002 __COUTTV__(sourceColumnNames_.size());
3005 if(!fillWithLooseColumnMatching_ && sourceColumnMissingCount_ > 0)
3007 __COUTV__(sourceColumnMissingCount_);
3008 __SS__ <<
"Can not ignore errors because not every column was found in the "
3010 <<
". Please see the details below:\n\n"
3015 if(sourceColumnNames_.size() ==
3018 for(
unsigned int i = 0; i < getNumberOfColumns(); ++i)
3019 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
3028 std::string TableView::getMismatchColumnInfo(
void)
const
3030 const std::set<std::string>& srcColNames = getSourceColumnNames();
3031 std::set<std::string> destColNames = getColumnStorageNames();
3033 __SS__ <<
"The source column size was found to be " << srcColNames.size()
3034 <<
", and the current number of columns for this table is "
3035 << getNumberOfColumns() <<
". This resulted in a count of "
3036 << getSourceColumnMismatch() <<
" source column mismatches, and a count of "
3037 << getSourceColumnMissing() <<
" table entries missing in "
3038 << getNumberOfRows() <<
" row(s) of data." << __E__;
3041 << srcColNames.size()
3042 <<
" Source column names in ALPHABETICAL order were as follows:\n";
3044 std::string preIndexStr =
"";
3045 for(
auto& srcColName : srcColNames)
3047 if(destColNames.find(srcColName) == destColNames.end())
3048 ss <<
"\n\t*** " << preIndexStr << index <<
". " << srcColName <<
" ***";
3050 ss <<
"\n\t" << preIndexStr << index <<
". " << srcColName;
3063 << destColNames.size()
3064 <<
" Current table column names in ALPHABETICAL order are as follows:\n";
3067 for(
auto& destColName : destColNames)
3069 if(srcColNames.find(destColName) == srcColNames.end())
3070 ss <<
"\n\t*** " << preIndexStr << index <<
". " << destColName <<
" ***";
3072 ss <<
"\n\t" << preIndexStr << index <<
". " << destColName;
3087 bool TableView::isURIEncodedCommentTheSame(
const std::string& comment)
const
3090 return comment_ == compareStr;
3135 const int& dataOffset ,
3136 const std::string& author ,
3137 const char rowDelimter ,
3138 const char colDelimter )
3140 int row = dataOffset;
3142 std::string currentValue =
"";
3143 bool insideQuotes =
false;
3144 int authorCol =
findColByType(TableViewColumnInfo::TYPE_AUTHOR);
3145 int timestampCol =
findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
3147 for(
size_t i = 0; i < data.size(); ++i)
3150 const char nextChar = (i + 1 < data.size() ? data[i + 1] :
' ');
3154 if(insideQuotes && nextChar ==
'"')
3157 currentValue +=
'"';
3163 insideQuotes = !insideQuotes;
3166 else if(c == rowDelimter && !insideQuotes)
3168 if(col == 0 && row >= (
int)getNumberOfRows())
3174 else if((c == colDelimter || c ==
'\r') && !insideQuotes)
3184 __COUT__ <<
"First row detected as column names." << __E__;
3192 setValue(time(0), row, timestampCol);
3216 __COUT__ <<
"First row detected as column names." << __E__;
3224 setValue(time(0), row, timestampCol);
3263 const int& dataOffset,
3264 const std::string& author)
3272 int j = data.find(
',', i);
3273 int k = data.find(
';', i);
3275 bool rowWasModified;
3276 unsigned int countRowsModified = 0;
3277 int authorCol =
findColByType(TableViewColumnInfo::TYPE_AUTHOR);
3278 int timestampCol =
findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
3281 while(k != (
int)(std::string::npos))
3283 rowWasModified =
false;
3284 if(r >= (
int)getNumberOfRows())
3288 rowWasModified =
true;
3291 while(j < k && j != (
int)(std::string::npos))
3296 if(c >= (
int)getNumberOfColumns() - 2)
3299 j = data.find(
',', i);
3305 rowWasModified =
true;
3308 j = data.find(
',', i);
3313 if(author !=
"" && rowWasModified)
3315 __COUTT__ <<
"Row=" << (int)r <<
" was modified!" << __E__;
3317 setValue(time(0), r, timestampCol);
3321 ++countRowsModified;
3327 j = data.find(
',', i);
3328 k = data.find(
';', i);
3332 while(r < (
int)getNumberOfRows())
3335 __COUT__ <<
"Row deleted: " << (int)r << __E__;
3336 ++countRowsModified;
3339 __COUT_INFO__ <<
"countRowsModified=" << countRowsModified << __E__;
3341 if(!countRowsModified)
3346 bool match = getColumnStorageNames().size() == getSourceColumnNames().size();
3349 for(
auto& destColName : getColumnStorageNames())
3350 if(getSourceColumnNames().find(destColName) ==
3351 getSourceColumnNames().end())
3353 __COUT__ <<
"Found column name mismach for '" << destColName
3354 <<
"'... So allowing same data!" << __E__;
3363 __SS__ <<
"No rows were modified! No reason to fill a view with same content."
3365 __COUT__ <<
"\n" << ss.str();
3375 sourceColumnNames_.clear();
3376 for(
unsigned int i = 0; i < getNumberOfColumns(); ++i)
3377 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
3399 const unsigned int& r,
3400 const unsigned int& c,
3401 const std::string& author)
3403 if(!(c < columnsInfo_.size() && r < getNumberOfRows()))
3405 __SS__ <<
"Invalid row (" << (int)r <<
") col (" << (
int)c <<
") requested!"
3406 <<
"Number of Rows = " << getNumberOfRows()
3407 <<
"Number of Columns = " << columnsInfo_.size() << __E__;
3413 std::string originalValueStr =
3437 theDataView_[r][c] = valueStr;
3441 else if(columnsInfo_[c].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
3453 setValue(time_t(strtol(valueStr.c_str(), 0, 10)), r, c);
3456 theDataView_[r][c] = valueStr;
3458 bool rowWasModified =
3459 (originalValueStr !=
3463 if(author !=
"" && rowWasModified)
3465 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << __E__;
3466 int authorCol =
findColByType(TableViewColumnInfo::TYPE_AUTHOR);
3467 int timestampCol =
findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
3469 setValue(time(0), r, timestampCol);
3472 return rowWasModified;
3476 void TableView::resizeDataView(
unsigned int nRows,
unsigned int nCols)
3480 theDataView_.resize(nRows, std::vector<std::string>(nCols));
3491 const std::string& author,
3493 incrementUniqueData ,
3496 const std::string& baseNameAutoUID ,
3497 unsigned int rowToAdd ,
3498 std::string childLinkIndex ,
3499 std::string groupId )
3502 if(rowToAdd == (
unsigned int)-1)
3503 rowToAdd = getNumberOfRows();
3505 theDataView_.resize(getNumberOfRows() + 1,
3506 std::vector<std::string>(getNumberOfColumns()));
3509 for(
unsigned int r = getNumberOfRows() - 2; r >= rowToAdd; --r)
3511 if(r == (
unsigned int)-1)
3513 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
3514 theDataView_[r + 1][col] = theDataView_[r][col];
3517 std::vector<std::string> defaultRowValues = getDefaultRowValues();
3520 std::string tmpString, baseString;
3524 std::string numString;
3529 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
3537 if(incrementUniqueData &&
3538 (col ==
getColUID() || columnsInfo_[col].isChildLinkGroupID() ||
3539 (getNumberOfRows() > 1 &&
3540 (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_DATA ||
3541 columnsInfo_[col].getType() ==
3542 TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA))))
3544 if(col ==
getColUID() || columnsInfo_[col].isChildLinkGroupID())
3546 rowToAdd, col, baseNameAutoUID );
3556 theDataView_[rowToAdd][col] = defaultRowValues[col];
3561 __COUT__ <<
"Row=" << rowToAdd <<
" was created!" << __E__;
3563 int authorCol =
findColByType(TableViewColumnInfo::TYPE_AUTHOR);
3564 int timestampCol =
findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
3565 setValue(author, rowToAdd, authorCol);
3566 setValue(time(0), rowToAdd, timestampCol);
3577 if(r >= (
int)getNumberOfRows())
3580 __SS__ <<
"Row " << (int)r
3581 <<
" is out of bounds (Row Count = " << getNumberOfRows()
3582 <<
") and can not be deleted." << __E__;
3586 theDataView_.erase(theDataView_.begin() + r);
3606 const unsigned int& c,
3608 std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>& linkPair)
const
3610 if(!(c < columnsInfo_.size()))
3612 __SS__ <<
"Invalid col (" << (int)c <<
") requested for child link!" << __E__;
3620 if((isGroup = columnsInfo_[c].isChildLinkGroupID()) ||
3621 columnsInfo_[c].isChildLinkUID())
3625 linkPair.second = c;
3626 std::string index = columnsInfo_[c].getChildLinkIndex();
3631 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
3637 else if(columnsInfo_[col].isChildLink() &&
3638 index == columnsInfo_[col].getChildLinkIndex())
3643 linkPair.first = col;
3649 __SS__ <<
"\tIn view: " << tableName_
3650 <<
", Can't find complete child link for column name "
3651 << columnsInfo_[c].getName() <<
". Child link index is '" << index
3652 <<
"' - is there a mismatch? Or was this intended to be the target of a "
3653 "Group Link (column type 'GroupID')? "
3658 if(!columnsInfo_[c].isChildLink())
3663 std::string index = columnsInfo_[c].getChildLinkIndex();
3668 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
3685 if(((columnsInfo_[col].isChildLinkUID() && !(isGroup =
false)) ||
3686 (columnsInfo_[col].isChildLinkGroupID() && (isGroup =
true))) &&
3687 index == columnsInfo_[col].getChildLinkIndex())
3692 linkPair.second = col;
3698 __SS__ <<
"\tIn view: " << tableName_
3699 <<
", Can't find complete child link id for column name "
3700 << 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 setToString(const std::set< T > &setToReturn, const std::string &delimeter=", ")
setToString ~
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)