1 #include "otsdaq/TableCore/TableView.h"
2 #include "otsdaq/TableCore/TableBase.h"
12 #define __MF_SUBJECT__ "TableView"
14 #define __COUT_HDR__ (tableName_ + "v" + version_.toString() + "\t<> ")
16 const unsigned int TableView::INVALID = -1;
19 TableView::TableView(
const std::string& tableName)
20 : uniqueStorageIdentifier_(tableName)
21 , tableName_(
TableBase::convertToCaps(uniqueStorageIdentifier_))
25 , creationTime_(time(0))
29 , colPriority_(INVALID)
30 , fillWithLooseColumnMatching_(false)
31 , sourceColumnMismatchCount_(0)
32 , sourceColumnMissingCount_(0)
34 uniqueStorageIdentifier_ =
"";
38 __SS__ <<
"Do not allow anonymous table view construction!" << __E__;
39 ss << StringMacros::stackTrace() << __E__;
46 TableView::~TableView(
void) {}
54 __SS__ <<
"Invalid use of operator=... Should not directly copy a TableView. Please "
55 "use TableView::copy(sourceView,author,comment)";
63 version_ = destinationVersion;
64 comment_ = src.comment_;
67 lastAccessTime_ = time(0);
68 columnsInfo_ = src.columnsInfo_;
69 theDataView_ = src.theDataView_;
70 sourceColumnNames_ = src.sourceColumnNames_;
98 unsigned int TableView::copyRows(
const std::string& author,
100 unsigned int srcOffsetRow ,
101 unsigned int srcRowsToCopy ,
102 unsigned int destOffsetRow ,
103 unsigned char generateUniqueDataColumns ,
104 const std::string& baseNameAutoUID )
110 unsigned int retRow = (
unsigned int)-1;
113 if (src.getNumberOfColumns() != getNumberOfColumns())
115 __SS__ <<
"Error! Number of Columns of source view must match destination view."
116 <<
"Dimension of source is [" << src.getNumberOfColumns() <<
"] and of destination is [" << getNumberOfColumns() <<
"]." << __E__;
120 unsigned int srcRows = src.getNumberOfRows();
122 for (
unsigned int r = 0; r < srcRowsToCopy; ++r)
124 if (r + srcOffsetRow >= srcRows)
127 destOffsetRow = addRow(author,
128 generateUniqueDataColumns ,
132 if (retRow == (
unsigned int)-1)
133 retRow = destOffsetRow;
136 for (
unsigned int col = 0; col < getNumberOfColumns(); ++col)
137 if (generateUniqueDataColumns &&
138 (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UID || columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_DATA ||
139 columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA))
142 theDataView_[destOffsetRow][col] = src.theDataView_[r + srcOffsetRow][col];
158 void TableView::init(
void)
166 std::set<std::string> colNameSet;
167 std::string capsColName, colName;
168 for (
auto& colInfo : columnsInfo_)
170 colName = colInfo.getStorageName();
171 if (colName ==
"COMMENT_DESCRIPTION")
174 for (
unsigned int i = 0; i < colName.size(); ++i)
176 if (colName[i] ==
'_')
178 capsColName += colName[i];
181 colNameSet.emplace(capsColName);
184 if (colNameSet.size() != columnsInfo_.size())
186 __SS__ <<
"Table Error:\t"
187 <<
" Columns names must be unique! There are " << columnsInfo_.size() <<
" columns and the unique name count is " << colNameSet.size()
209 if (sourceColumnNames_.size() == 0)
210 for (
unsigned int i = 0; i < getNumberOfColumns(); ++i)
211 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
215 if ((colPos = findColByType(TableViewColumnInfo::TYPE_COMMENT)) != INVALID)
217 if (columnsInfo_[colPos].getName() != TableViewColumnInfo::COL_NAME_COMMENT)
219 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT <<
" data type column must have name=" << TableViewColumnInfo::COL_NAME_COMMENT
224 if (findColByType(TableViewColumnInfo::TYPE_COMMENT, colPos + 1) != INVALID)
226 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT <<
" data type in column " << columnsInfo_[colPos].getName()
227 <<
" is repeated. This is not allowed." << __E__;
231 if (colPos != getNumberOfColumns() - 3)
233 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT <<
" data type column must be 3rd to last (in column "
234 << getNumberOfColumns() - 3 <<
")." << __E__;
240 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT <<
" data type column "
241 <<
" is missing. This is not allowed." << __E__;
246 if ((colPos = findColByType(TableViewColumnInfo::TYPE_AUTHOR)) != INVALID)
248 if (findColByType(TableViewColumnInfo::TYPE_AUTHOR, colPos + 1) != INVALID)
250 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR <<
" data type in column " << columnsInfo_[colPos].getName()
251 <<
" is repeated. This is not allowed." << __E__;
255 if (colPos != getNumberOfColumns() - 2)
257 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR <<
" data type column must be 2nd to last (in column "
258 << getNumberOfColumns() - 2 <<
")." << __E__;
264 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR <<
" data type column "
265 <<
" is missing. This is not allowed." << __E__;
270 if ((colPos = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP)) != INVALID)
272 if (findColByType(TableViewColumnInfo::TYPE_TIMESTAMP, colPos + 1) != INVALID)
274 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP <<
" data type in column " << columnsInfo_[colPos].getName()
275 <<
" is repeated. This is not allowed." << __E__;
279 if (colPos != getNumberOfColumns() - 1)
281 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP <<
" data type column must be last (in column " << getNumberOfColumns() - 1
283 __COUT_ERR__ <<
"\n" << ss.str();
289 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP <<
" data type column "
290 <<
" is missing. This is not allowed." << __E__;
297 std::set<std::string > uidSet;
298 for (
unsigned int row = 0; row < getNumberOfRows(); ++row)
300 if (uidSet.find(theDataView_[row][colUID_]) != uidSet.end())
302 __SS__ << (
"Entries in UID are not unique. Specifically at row=" + std::to_string(row) +
" value=" + theDataView_[row][colUID_]) << __E__;
306 if (theDataView_[row][colUID_].size() == 0)
308 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' "
309 <<
" was identified. UIDs must contain at least 1 character." << __E__;
313 for (
unsigned int i = 0; i < theDataView_[row][colUID_].size(); ++i)
314 if (!((theDataView_[row][colUID_][i] >=
'A' && theDataView_[row][colUID_][i] <=
'Z') ||
315 (theDataView_[row][colUID_][i] >=
'a' && theDataView_[row][colUID_][i] <=
'z') ||
316 (theDataView_[row][colUID_][i] >=
'0' && theDataView_[row][colUID_][i] <=
'9') ||
317 (theDataView_[row][colUID_][i] ==
'-' || theDataView_[row][colUID_][i] ==
'_')))
319 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' "
320 <<
" was identified. UIDs must contain only letters, numbers,"
321 <<
"dashes, and underscores." << __E__;
325 uidSet.insert(theDataView_[row][colUID_]);
327 if (uidSet.size() != getNumberOfRows())
329 __SS__ <<
"Entries in UID are not unique!"
330 <<
"There are " << getNumberOfRows() <<
" records and the unique UID count is " << uidSet.size() << __E__;
335 colPos = (
unsigned int)-1;
336 while ((colPos = findColByType(TableViewColumnInfo::TYPE_UNIQUE_DATA, colPos + 1)) != INVALID)
338 std::set<std::string > uDataSet;
339 for (
unsigned int row = 0; row < getNumberOfRows(); ++row)
341 if (uDataSet.find(theDataView_[row][colPos]) != uDataSet.end())
343 __SS__ <<
"Entries in Unique Data column " << columnsInfo_[colPos].getName()
344 << (
" are not unique. Specifically at row=" + std::to_string(row) +
" value=" + theDataView_[row][colPos]) << __E__;
347 uDataSet.insert(theDataView_[row][colPos]);
349 if (uDataSet.size() != getNumberOfRows())
351 __SS__ <<
"Entries in Unique Data column " << columnsInfo_[colPos].getName() <<
" are not unique!"
352 <<
"There are " << getNumberOfRows() <<
" records and the unique data count is " << uDataSet.size() << __E__;
359 colPos = (
unsigned int)-1;
360 while ((colPos = findColByType(TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA, colPos + 1)) != INVALID)
365 for (
unsigned int groupIdColPos = 0; groupIdColPos < columnsInfo_.size(); ++groupIdColPos)
366 if (columnsInfo_[groupIdColPos].isGroupID())
368 std::map<std::string , std::pair<
unsigned int , std::set<std::string >>> uGroupDataSets;
370 for (
unsigned int row = 0; row < getNumberOfRows(); ++row)
372 auto groupIds = getSetOfGroupIDs(groupIdColPos, row);
374 for (
const auto& groupId : groupIds)
376 uGroupDataSets[groupId].first++;
378 if (uGroupDataSets[groupId].second.find(theDataView_[row][colPos]) != uGroupDataSets[groupId].second.end())
380 __SS__ <<
"Entries in Unique Group Data column " << colPos <<
":" << columnsInfo_[colPos].getName()
381 <<
" are not unique for group ID '" << groupId <<
".' Specifically at row=" << std::to_string(row)
382 <<
" value=" << theDataView_[row][colPos] << __E__;
385 uGroupDataSets[groupId].second.insert(theDataView_[row][colPos]);
389 for (
const auto& groupPair : uGroupDataSets)
390 if (uGroupDataSets[groupPair.first].second.size() != uGroupDataSets[groupPair.first].first)
392 __SS__ <<
"Entries in Unique Data column " << columnsInfo_[colPos].getName() <<
" are not unique for group '" << groupPair.first
394 <<
"There are " << uGroupDataSets[groupPair.first].first <<
" records and the unique data count is "
395 << uGroupDataSets[groupPair.first].second.size() << __E__;
401 auto rowDefaults = getDefaultRowValues();
408 std::set<std::string> groupIdIndexes, childLinkIndexes, childLinkIdLabels;
409 unsigned int groupIdIndexesCount = 0, childLinkIndexesCount = 0, childLinkIdLabelsCount = 0;
411 std::pair<
unsigned int ,
unsigned int > tmpLinkPair;
413 for (
unsigned int col = 0; col < getNumberOfColumns(); ++col)
415 if (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
417 const std::vector<std::string>& theDataChoices = columnsInfo_[col].getDataChoices();
420 if (theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=1")
424 for (
unsigned int row = 0; row < getNumberOfRows(); ++row)
428 if (theDataView_[row][col] == rowDefaults[col])
431 for (
const auto& choice : theDataChoices)
433 if (theDataView_[row][col] == choice)
441 __SS__ << getTableName() <<
" Error:\t'" << theDataView_[row][col] <<
"' in column " << columnsInfo_[col].getName()
442 <<
" is not a valid Fixed Choice option. "
443 <<
"Possible values are as follows: ";
445 for (
unsigned int i = 0; i < columnsInfo_[col].getDataChoices().size(); ++i)
449 ss << columnsInfo_[col].getDataChoices()[i];
456 else if (columnsInfo_[col].isChildLink())
460 const std::vector<std::string>& theDataChoices = columnsInfo_[col].getDataChoices();
463 if (!theDataChoices.size() || theDataChoices[0] ==
"arbitraryBool=1")
467 bool skipOne = (theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=0");
471 for (
unsigned int row = 0; row < getNumberOfRows(); ++row)
476 for (
const auto& choice : theDataChoices)
478 if (skipOne && !hasSkipped)
484 if (theDataView_[row][col] == choice)
492 __SS__ << getTableName() <<
" Error:\t the value '" << theDataView_[row][col] <<
"' in column " << columnsInfo_[col].getName()
493 <<
" is not a valid Fixed Choice option. "
494 <<
"Possible values are as follows: ";
499 for (
unsigned int i = skipOne ? 1 : 0; i < columnsInfo_[col].getDataChoices().size(); ++i)
501 if (i > (skipOne ? 1 : 0))
503 ss << columnsInfo_[col].getDataChoices()[i];
510 else if (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_ON_OFF)
511 for (
unsigned int row = 0; row < getNumberOfRows(); ++row)
513 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" || theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
514 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_ON;
515 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"off" || theDataView_[row][col] ==
"Off" ||
516 theDataView_[row][col] ==
"OFF")
517 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_OFF;
520 __SS__ << getTableName() <<
" Error:\t the value '" << theDataView_[row][col] <<
"' in column " << columnsInfo_[col].getName()
521 <<
" is not a valid Type (On/Off) std::string. Possible "
522 "values are 1, on, On, ON, 0, off, Off, OFF."
527 else if (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_TRUE_FALSE)
528 for (
unsigned int row = 0; row < getNumberOfRows(); ++row)
530 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" || theDataView_[row][col] ==
"True" ||
531 theDataView_[row][col] ==
"TRUE")
532 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_TRUE;
533 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"false" || theDataView_[row][col] ==
"False" ||
534 theDataView_[row][col] ==
"FALSE")
535 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_FALSE;
538 __SS__ << getTableName() <<
" Error:\t the value '" << theDataView_[row][col] <<
"' in column " << columnsInfo_[col].getName()
539 <<
" is not a valid Type (True/False) std::string. "
540 "Possible values are 1, true, True, TRUE, 0, false, "
546 else if (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_YES_NO)
547 for (
unsigned int row = 0; row < getNumberOfRows(); ++row)
549 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" || theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
550 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_YES;
551 else if (theDataView_[row][col] ==
"0" || theDataView_[row][col] ==
"no" || theDataView_[row][col] ==
"No" || theDataView_[row][col] ==
"NO")
552 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_NO;
555 __SS__ << getTableName() <<
" Error:\t the value '" << theDataView_[row][col] <<
"' in column " << columnsInfo_[col].getName()
556 <<
" is not a valid Type (Yes/No) std::string. Possible "
557 "values are 1, yes, Yes, YES, 0, no, No, NO."
562 else if (columnsInfo_[col].isGroupID())
564 colLinkGroupIDs_[columnsInfo_[col].getChildLinkIndex()] = col;
566 groupIdIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
567 ++groupIdIndexesCount;
569 else if (columnsInfo_[col].isChildLink())
572 for (
unsigned int row = 0; row < getNumberOfRows(); ++row)
573 if (theDataView_[row][col] ==
"NoLink" || theDataView_[row][col] ==
"No_Link" || theDataView_[row][col] ==
"NOLINK" ||
574 theDataView_[row][col] ==
"NO_LINK" || theDataView_[row][col] ==
"Nolink" || theDataView_[row][col] ==
"nolink" ||
575 theDataView_[row][col] ==
"noLink")
576 theDataView_[row][col] = TableViewColumnInfo::DATATYPE_LINK_DEFAULT;
579 childLinkIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
580 ++childLinkIndexesCount;
583 if (columnsInfo_[col].getDataType() != TableViewColumnInfo::DATATYPE_STRING)
585 __SS__ << getTableName() <<
" Error:\t"
586 <<
"Column " << col <<
" with name '" << columnsInfo_[col].getName() <<
"' is a Child Link column and has an illegal data type of '"
587 << columnsInfo_[col].getDataType() <<
"'. The data type for Child Link columns must be " << TableViewColumnInfo::DATATYPE_STRING
593 getChildLink(col, tmpIsGroup, tmpLinkPair);
595 else if (columnsInfo_[col].isChildLinkUID() ||
596 columnsInfo_[col].isChildLinkGroupID())
599 childLinkIdLabels.emplace(columnsInfo_[col].getChildLinkIndex());
600 ++childLinkIdLabelsCount;
603 for (
unsigned int row = 0; row < getNumberOfRows(); ++row)
604 if (theDataView_[row][col] ==
"")
605 theDataView_[row][col] = rowDefaults[col];
608 getChildLink(col, tmpIsGroup, tmpLinkPair);
613 if (groupIdIndexes.size() != groupIdIndexesCount)
615 __SS__ << (
"GroupId Labels are not unique!") <<
"There are " << groupIdIndexesCount <<
" GroupId Labels and the unique count is "
616 << groupIdIndexes.size() << __E__;
619 if (childLinkIndexes.size() != childLinkIndexesCount)
621 __SS__ << (
"Child Link Labels are not unique!") <<
"There are " << childLinkIndexesCount <<
" Child Link Labels and the unique count is "
622 << childLinkIndexes.size() << __E__;
625 if (childLinkIdLabels.size() != childLinkIdLabelsCount)
627 __SS__ << (
"Child Link ID Labels are not unique!") <<
"There are " << childLinkIdLabelsCount <<
" Child Link ID Labels and the unique count is "
628 << childLinkIdLabels.size() << __E__;
634 __COUT__ <<
"Error occured in TableView::init() for version=" << version_ << __E__;
644 void TableView::getValue(std::string& value,
unsigned int row,
unsigned int col,
bool doConvertEnvironmentVariables)
const
646 if (!(row < getNumberOfRows() && col < theDataView_[row].size()))
648 __SS__ <<
"Invalid row col requested " << row <<
"," << col <<
" vs " << getNumberOfRows() <<
"," << columnsInfo_.size() <<
"/"
649 << theDataView_[row].size() << __E__;
653 value = validateValueForColumn(theDataView_[row][col], col, doConvertEnvironmentVariables);
661 std::string TableView::validateValueForColumn(
const std::string& value,
unsigned int col,
bool doConvertEnvironmentVariables)
const
663 if (col >= columnsInfo_.size())
665 __SS__ <<
"Invalid col requested" << __E__;
669 if (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA && value == columnsInfo_[col].getDefaultValue())
673 std::vector<std::string> choices = columnsInfo_[col].getDataChoices();
676 bool skipOne = (choices.size() && choices[0].find(
"arbitraryBool=") == 0);
677 size_t index = (skipOne ? 1 : 0);
678 if (choices.size() > index)
680 return doConvertEnvironmentVariables ? StringMacros::convertEnvironmentVariables(choices[index])
685 if (columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_STRING)
686 return doConvertEnvironmentVariables ? StringMacros::convertEnvironmentVariables(value) : value;
687 else if (columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
689 return StringMacros::getTimestampString(doConvertEnvironmentVariables ? StringMacros::convertEnvironmentVariables(value) : value);
702 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType() <<
" in configuration " << tableName_
703 <<
" at column=" << columnsInfo_[col].getName() <<
" for getValue with type '" << StringMacros::demangleTypeName(
typeid(std::string).name())
715 std::string TableView::getValueAsString(
unsigned int row,
unsigned int col,
bool doConvertEnvironmentVariables)
const
717 if (!(col < columnsInfo_.size() && row < getNumberOfRows()))
719 __SS__ << (
"Invalid row col requested") << __E__;
725 if (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_ON_OFF)
727 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" || theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
728 return TableViewColumnInfo::TYPE_VALUE_ON;
730 return TableViewColumnInfo::TYPE_VALUE_OFF;
732 else if (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_TRUE_FALSE)
734 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" || theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
735 return TableViewColumnInfo::TYPE_VALUE_TRUE;
737 return TableViewColumnInfo::TYPE_VALUE_FALSE;
739 else if (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_YES_NO)
741 if (theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" || theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
742 return TableViewColumnInfo::TYPE_VALUE_YES;
744 return TableViewColumnInfo::TYPE_VALUE_NO;
748 return doConvertEnvironmentVariables ? StringMacros::convertEnvironmentVariables(theDataView_[row][col]) : theDataView_[row][col];
757 std::string TableView::getEscapedValueAsString(
unsigned int row,
unsigned int col,
bool doConvertEnvironmentVariables)
const
759 std::string val = getValueAsString(row, col, doConvertEnvironmentVariables);
760 std::string retVal =
"";
761 retVal.reserve(val.size());
762 for (
unsigned int i = 0; i < val.size(); ++i)
766 else if (val[i] ==
'\t')
768 else if (val[i] ==
'\r')
773 if (val[i] ==
'"' || val[i] ==
'\\')
784 void TableView::setValue(
const std::string& value,
unsigned int row,
unsigned int col)
786 if (!(col < columnsInfo_.size() && row < getNumberOfRows()))
788 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
792 if (columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_STRING)
793 theDataView_[row][col] = value;
797 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType() <<
" in configuration " << tableName_
798 <<
" at column=" << columnsInfo_[col].getName() <<
" for setValue with type '" << StringMacros::demangleTypeName(
typeid(value).name()) <<
"'"
805 void TableView::setValue(
const char* value,
unsigned int row,
unsigned int col) { setValue(std::string(value), row, col); }
810 void TableView::setValueAsString(
const std::string& value,
unsigned int row,
unsigned int col)
812 if (!(col < columnsInfo_.size() && row < getNumberOfRows()))
814 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
818 theDataView_[row][col] = value;
828 const std::string& TableView::setUniqueColumnValue(
unsigned int row,
830 std::string baseValueAsString ,
831 bool doMathAppendStrategy )
833 if (!(col < columnsInfo_.size() && row < getNumberOfRows()))
835 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
845 bool firstConflict =
true;
846 int maxUniqueData = -1;
847 std::string tmpString =
"";
850 std::string numString;
851 std::string opString;
852 char indexString[1000];
858 for (
unsigned int r = 0; r < getNumberOfRows(); ++r)
866 tmpString = theDataView_[r][col];
870 for (index = tmpString.length() - 1; index < tmpString.length(); --index)
874 if (!(tmpString[index] >=
'0' && tmpString[index] <=
'9'))
881 if (tmpString.length() && foundAny)
884 numString = tmpString.substr(index + 1);
887 tmpString = tmpString.substr(0, index + 1);
889 if (doMathAppendStrategy && tmpString.size())
893 for (index = tmpString.length() - 1; index < tmpString.length(); --index)
897 if (!(tmpString[index] ==
'+' || tmpString[index] ==
' '))
905 opString = tmpString.substr(index + 1);
908 tmpString = tmpString.substr(0, index + 1);
914 if (baseValueAsString !=
"" && tmpString != baseValueAsString)
923 if (baseValueAsString.size() && baseValueAsString[baseValueAsString.size() - 1] >=
'0' && baseValueAsString[baseValueAsString.size() - 1] <=
'9')
924 baseValueAsString +=
'_';
926 firstConflict =
false;
930 sscanf(numString.c_str(),
"%u", &index);
932 if ((
int)index > maxUniqueData)
934 maxUniqueData = (int)index;
936 if (baseValueAsString ==
"")
937 baseValueAsString = tmpString;
940 else if (maxUniqueData < 0 && (baseValueAsString ==
"" || tmpString == baseValueAsString))
945 if (baseValueAsString.size() && baseValueAsString[baseValueAsString.size() - 1] >=
'0' && baseValueAsString[baseValueAsString.size() - 1] <=
'9')
946 baseValueAsString +=
'_';
948 firstConflict =
false;
957 if (maxUniqueData == -1)
958 theDataView_[row][col] = baseValueAsString;
963 sprintf(indexString,
"%u", maxUniqueData);
968 if (doMathAppendStrategy)
969 theDataView_[row][col] = baseValueAsString +
" + " + indexString;
971 theDataView_[row][col] = baseValueAsString + indexString;
974 __COUT__ <<
"New unique data entry is data[" << row <<
"][" << col <<
"] = '" << theDataView_[row][col] <<
"'" << __E__;
978 return theDataView_[row][col];
984 unsigned int TableView::initColUID(
void)
986 if (colUID_ != INVALID)
990 colUID_ = findColByType(TableViewColumnInfo::TYPE_UID);
991 if (colUID_ == INVALID)
993 __COUT__ <<
"Column Types: " << __E__;
994 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
995 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << __E__;
996 __SS__ <<
"\tMissing UID Column in table named '" << tableName_ <<
"'" << __E__;
1005 unsigned int TableView::getColUID(
void)
const
1007 if (colUID_ != INVALID)
1010 __COUT__ <<
"Column Types: " << __E__;
1011 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1012 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << __E__;
1014 __SS__ << (
"Missing UID Column in config named " + tableName_ +
". (Possibly TableView was just not initialized?" +
1015 " This is the const call so can not alter class members)")
1018 ss << StringMacros::stackTrace() << __E__;
1026 unsigned int TableView::initColStatus(
void)
1028 if (colStatus_ != INVALID)
1032 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1033 if (columnsInfo_[col].getName() == TableViewColumnInfo::COL_NAME_STATUS)
1038 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1039 if (columnsInfo_[col].getName() == TableViewColumnInfo::COL_NAME_ENABLED)
1047 __SS__ <<
"\tMissing column named '" << TableViewColumnInfo::COL_NAME_STATUS <<
"' or '" << TableViewColumnInfo::COL_NAME_ENABLED <<
"' in table '"
1048 << tableName_ <<
".'" << __E__;
1049 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1050 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1051 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << __E__;
1060 unsigned int TableView::initColPriority(
void)
1062 if (colPriority_ != INVALID)
1063 return colPriority_;
1066 colPriority_ = findCol(
"*" + TableViewColumnInfo::COL_NAME_PRIORITY);
1067 if (colPriority_ == INVALID)
1069 __SS__ <<
"\tMissing column named '" << TableViewColumnInfo::COL_NAME_PRIORITY <<
"' in table '" << tableName_ <<
".'" << __E__;
1070 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1071 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1072 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << __E__;
1076 return colPriority_;
1083 unsigned int TableView::getColStatus(
void)
const
1085 if (colStatus_ != INVALID)
1088 __SS__ <<
"\tMissing column named '" << TableViewColumnInfo::COL_NAME_STATUS <<
"' or '" << TableViewColumnInfo::COL_NAME_ENABLED <<
"' in table '"
1089 << tableName_ <<
".'"
1090 <<
" (The Status column is identified when the TableView is initialized)" << __E__;
1092 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1093 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1094 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << __E__;
1098 ss << StringMacros::stackTrace() << __E__;
1110 unsigned int TableView::getColPriority(
void)
const
1112 if (colPriority_ != INVALID)
1113 return colPriority_;
1115 __SS__ <<
"Priority column was not found... \nColumn Types: " << __E__;
1117 ss <<
"Missing " << TableViewColumnInfo::COL_NAME_PRIORITY <<
" Column in table named '" << tableName_
1118 <<
".' (The Priority column is identified when the TableView is initialized)"
1122 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1123 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1124 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << __E__;
1127 ss << StringMacros::stackTrace() << __E__;
1135 void TableView::addRowToGroup(
const unsigned int& row,
1136 const unsigned int& col,
1137 const std::string& groupID)
1140 if (isEntryInGroupCol(row, col, groupID))
1142 __SS__ <<
"GroupID (" << groupID <<
") added to row (" << row <<
" is already present!" << __E__;
1151 if (getDataView()[row][col] ==
"" || getDataView()[row][col] == getDefaultRowValues()[col])
1152 setValue(groupID, row, col);
1154 setValue(groupID +
" | " + getDataView()[row][col], row, col);
1165 std::vector<
unsigned int > TableView::getGroupRows(
const unsigned int groupIdCol,
1166 const std::string& groupID,
1167 bool onlyStatusTrue ,
1168 bool orderedByPriority )
const
1170 std::vector<
unsigned int > retVector;
1171 std::vector<std::vector<
unsigned int >> groupRowVectors = getGroupRowsInVectors(groupIdCol, groupID, onlyStatusTrue, orderedByPriority);
1173 for (
const auto& groupRowVector : groupRowVectors)
1174 for (
const auto& groupRow : groupRowVector)
1175 retVector.push_back(groupRow);
1186 std::vector<std::vector<
unsigned int >> TableView::getGroupRowsByPriority(
const unsigned int groupIdCol,
1187 const std::string& groupID,
1188 bool onlyStatusTrue )
const
1190 return getGroupRowsInVectors(groupIdCol, groupID, onlyStatusTrue,
true );
1201 std::vector<std::vector<
unsigned int >> TableView::getGroupRowsInVectors(
const unsigned int groupIdCol,
1202 const std::string& groupID,
1203 bool onlyStatusTrue,
1204 bool orderedByPriority)
const
1206 std::map<uint64_t , std::vector<
unsigned int >> mapByPriority;
1207 std::vector<std::vector<
unsigned int >> retVector;
1208 uint64_t tmpPriority;
1211 if (!(orderedByPriority && colPriority_ != INVALID))
1212 retVector.push_back(std::vector<unsigned int /*group row*/>());
1214 for (
unsigned int r = 0; r < getNumberOfRows(); ++r)
1215 if (groupID ==
"" || groupID ==
"*" || groupIdCol == INVALID || isEntryInGroupCol(r, groupIdCol, groupID))
1218 if (onlyStatusTrue && colStatus_ != INVALID)
1220 getValue(tmpStatus, r, colStatus_);
1226 if (orderedByPriority && colPriority_ != INVALID)
1228 getValue(tmpPriority, r, colPriority_);
1230 mapByPriority[tmpPriority ? tmpPriority : 100].push_back(r);
1233 retVector[0].push_back(r);
1236 if (orderedByPriority && colPriority_ != INVALID)
1240 for (
const auto& priorityChildRowVector : mapByPriority)
1242 retVector.push_back(std::vector<unsigned int /*group row*/>());
1243 for (
const auto& priorityChildRow : priorityChildRowVector.second)
1244 retVector[retVector.size() - 1].push_back(priorityChildRow);
1247 __COUT__ <<
"Returning priority children list." << __E__;
1259 bool TableView::removeRowFromGroup(
const unsigned int& row,
const unsigned int& col,
const std::string& groupNeedle,
bool deleteRowIfNoGroupLeft)
1261 __COUT__ <<
"groupNeedle " << groupNeedle << __E__;
1262 std::set<std::string> groupIDList;
1263 if (!isEntryInGroupCol(row, col, groupNeedle, &groupIDList))
1265 __SS__ <<
"GroupID (" << groupNeedle <<
") removed from row (" << row <<
") was already removed!" << __E__;
1274 std::string newValue =
"";
1275 unsigned int cnt = 0;
1276 for (
const auto& groupID : groupIDList)
1279 if (groupID == groupNeedle)
1284 newValue += groupID;
1287 bool wasDeleted =
false;
1288 if (deleteRowIfNoGroupLeft && newValue ==
"")
1290 __COUT__ <<
"Delete row since it no longer part of any group." << __E__;
1295 setValue(newValue, row, col);
1308 bool TableView::isEntryInGroup(
const unsigned int& r,
const std::string& childLinkIndex,
const std::string& groupNeedle)
const
1310 unsigned int c = getLinkGroupIDColumn(childLinkIndex);
1312 return isEntryInGroupCol(r, c, groupNeedle);
1324 bool TableView::isEntryInGroupCol(
const unsigned int& r,
const unsigned int& c,
const std::string& groupNeedle, std::set<std::string>* groupIDList)
const
1326 if (r >= getNumberOfRows() || c >= getNumberOfColumns())
1328 __SS__ <<
"Invalid row/col requested!" << __E__;
1329 ss << StringMacros::stackTrace() << __E__;
1340 for (; j < theDataView_[r][c].size(); ++j)
1341 if ((theDataView_[r][c][j] ==
' ' ||
1342 theDataView_[r][c][j] ==
'|') &&
1345 else if ((theDataView_[r][c][j] ==
' ' ||
1346 theDataView_[r][c][j] ==
'|') &&
1350 groupIDList->emplace(theDataView_[r][c].substr(i, j - i));
1354 if (groupNeedle == theDataView_[r][c].substr(i, j - i))
1367 groupIDList->emplace(theDataView_[r][c].substr(i, j - i));
1371 if (groupNeedle == theDataView_[r][c].substr(i, j - i))
1386 std::set<std::string> TableView::getSetOfGroupIDs(
const std::string& childLinkIndex,
unsigned int r)
const
1388 return getSetOfGroupIDs(getLinkGroupIDColumn(childLinkIndex), r);
1390 std::set<std::string> TableView::getSetOfGroupIDs(
const unsigned int& c,
unsigned int r)
const
1394 std::set<std::string> retSet;
1399 if (r != (
unsigned int)-1)
1401 if (r >= getNumberOfRows())
1403 __SS__ <<
"Invalid row requested!" << __E__;
1407 StringMacros::getSetFromString(theDataView_[r][c], retSet);
1435 for (r = 0; r < getNumberOfRows(); ++r)
1437 StringMacros::getSetFromString(theDataView_[r][c], retSet);
1485 unsigned int TableView::getLinkGroupIDColumn(
const std::string& childLinkIndex)
const
1487 if (!childLinkIndex.size())
1489 __SS__ <<
"Empty childLinkIndex string parameter!" << __E__;
1490 ss << StringMacros::stackTrace() << __E__;
1494 const char* needleChildLinkIndex = &childLinkIndex[0];
1498 size_t spacePos = childLinkIndex.find(
' ');
1499 if (spacePos != std::string::npos && spacePos + 1 < childLinkIndex.size())
1502 needleChildLinkIndex = &childLinkIndex[spacePos + 1];
1505 std::map<std::string, unsigned int>::const_iterator it = colLinkGroupIDs_.find(needleChildLinkIndex);
1507 colLinkGroupIDs_.end())
1511 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1512 if (needleChildLinkIndex == columnsInfo_[col].getChildLinkIndex())
1515 __SS__ <<
"Error! Incompatible table for this group link! Table '" << tableName_ <<
"' is missing a GroupID column with data type '"
1516 << TableViewColumnInfo::TYPE_START_GROUP_ID <<
"-" << needleChildLinkIndex <<
"'.\n\n"
1517 <<
"Note: you can separate the child GroupID column data type from "
1518 <<
"the parent GroupLink column data type; this is accomplished by using a space "
1519 <<
"character at the parent level - the string after the space will be treated "
1521 <<
"child GroupID column data type." << __E__;
1522 ss <<
"Existing Column GroupIDs: " << __E__;
1523 for (
auto& groupIdColPair : colLinkGroupIDs_)
1524 ss <<
"\t" << groupIdColPair.first <<
" : col-" << groupIdColPair.second << __E__;
1526 ss <<
"Existing Column Types: " << __E__;
1527 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1528 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName() << __E__;
1530 ss << StringMacros::stackTrace() << __E__;
1536 unsigned int TableView::findRow(
unsigned int col,
const std::string& value,
unsigned int offsetRow,
bool doNotThrow )
const
1538 for (
unsigned int row = offsetRow; row < theDataView_.size(); ++row)
1540 if (theDataView_[row][col] == value)
1544 return TableView::INVALID;
1546 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find value=" << value <<
" in column named " << columnsInfo_[col].getName()
1547 <<
" with type=" << columnsInfo_[col].getType() << __E__;
1555 unsigned int TableView::findRowInGroup(
1556 unsigned int col,
const std::string& value,
const std::string& groupId,
const std::string& childLinkIndex,
unsigned int offsetRow)
const
1558 unsigned int groupIdCol = getLinkGroupIDColumn(childLinkIndex);
1559 for (
unsigned int row = offsetRow; row < theDataView_.size(); ++row)
1561 if (theDataView_[row][col] == value && isEntryInGroupCol(row, groupIdCol, groupId))
1565 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find in group the value=" << value <<
" in column named '" << columnsInfo_[col].getName()
1566 <<
"' with type=" << columnsInfo_[col].getType() <<
" and GroupID: '" << groupId <<
"' in column '" << groupIdCol
1567 <<
"' with GroupID child link index '" << childLinkIndex <<
"'" << __E__;
1576 unsigned int TableView::findCol(
const std::string& wildCardName)
const
1578 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1579 if (StringMacros::wildCardMatch(wildCardName , columnsInfo_[col].getName() ))
1582 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find column named '" << wildCardName <<
"'" << __E__;
1583 ss <<
"Existing columns:\n";
1584 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1585 ss <<
"\t" << columnsInfo_[col].getName() <<
"\n";
1587 ss << StringMacros::stackTrace() << __E__;
1597 unsigned int TableView::findColByType(
const std::string& type,
int startingCol)
const
1599 for (
unsigned int col = startingCol; col < columnsInfo_.size(); ++col)
1600 if (columnsInfo_[col].getType() == type)
1608 const std::string& TableView::getUniqueStorageIdentifier(
void)
const {
return uniqueStorageIdentifier_; }
1611 const std::string& TableView::getTableName(
void)
const {
return tableName_; }
1614 const TableVersion& TableView::getVersion(
void)
const {
return version_; }
1617 const std::string& TableView::getComment(
void)
const {
return comment_; }
1620 const std::string& TableView::getAuthor(
void)
const {
return author_; }
1623 const time_t& TableView::getCreationTime(
void)
const {
return creationTime_; }
1626 const time_t& TableView::getLastAccessTime(
void)
const {
return lastAccessTime_; }
1629 const bool& TableView::getLooseColumnMatching(
void)
const {
return fillWithLooseColumnMatching_; }
1633 unsigned int TableView::getDataColumnSize(
void)
const
1636 if (!getNumberOfRows())
1637 return getNumberOfColumns();
1638 return theDataView_[0].size();
1644 const unsigned int& TableView::getSourceColumnMismatch(
void)
const {
return sourceColumnMismatchCount_; }
1649 const unsigned int& TableView::getSourceColumnMissing(
void)
const {
return sourceColumnMissingCount_; }
1654 const std::set<std::string>& TableView::getSourceColumnNames(
void)
const {
return sourceColumnNames_; }
1657 std::set<std::string> TableView::getColumnNames(
void)
const
1659 std::set<std::string> retSet;
1660 for (
auto& colInfo : columnsInfo_)
1661 retSet.emplace(colInfo.getName());
1666 std::map<std::string,
unsigned int > TableView::getColumnNamesMap(
void)
const
1668 std::map<std::string,
unsigned int > retMap;
1670 for (
auto& colInfo : columnsInfo_)
1671 retMap.emplace(std::make_pair(colInfo.getName(), c++));
1676 std::set<std::string> TableView::getColumnStorageNames(
void)
const
1678 std::set<std::string> retSet;
1679 for (
auto& colInfo : columnsInfo_)
1680 retSet.emplace(colInfo.getStorageName());
1685 std::vector<std::string> TableView::getDefaultRowValues(
void)
const
1687 std::vector<std::string> retVec;
1690 for (
unsigned int col = 0; col < getNumberOfColumns(); ++col)
1697 if (columnsInfo_[col].isChildLink())
1699 const std::vector<std::string>& theDataChoices = columnsInfo_[col].getDataChoices();
1702 if (!theDataChoices.size() ||
1703 theDataChoices[0] ==
"arbitraryBool=1")
1704 retVec.push_back(columnsInfo_[col].getDefaultValue());
1707 bool skipOne = (theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=0");
1712 bool foundDefault =
false;
1714 for (
const auto& choice : theDataChoices)
1715 if (skipOne && !hasSkipped)
1720 else if (choice == columnsInfo_[col].getDefaultValue())
1722 foundDefault =
true;
1727 if (!foundDefault && theDataChoices.size() > (skipOne ? 1 : 0))
1728 retVec.push_back(theDataChoices[(skipOne ? 1 : 0)]);
1730 retVec.push_back(columnsInfo_[col].getDefaultValue());
1734 retVec.push_back(columnsInfo_[col].getDefaultValue());
1741 unsigned int TableView::getNumberOfRows(
void)
const {
return theDataView_.size(); }
1744 unsigned int TableView::getNumberOfColumns(
void)
const {
return columnsInfo_.size(); }
1747 const TableView::DataView& TableView::getDataView(
void)
const {
return theDataView_; }
1756 const std::vector<TableViewColumnInfo>& TableView::getColumnsInfo(
void)
const {
return columnsInfo_; }
1759 std::vector<TableViewColumnInfo>* TableView::getColumnsInfoP(
void) {
return &columnsInfo_; }
1763 if (column >= columnsInfo_.size())
1765 __SS__ <<
"\nCan't find column " << column
1766 <<
"\n\n\n\nThe column info is likely missing due to incomplete "
1767 "Configuration View filling.\n\n"
1769 ss << StringMacros::stackTrace() << __E__;
1772 return columnsInfo_[column];
1777 void TableView::setUniqueStorageIdentifier(
const std::string& storageUID) { uniqueStorageIdentifier_ = storageUID; }
1783 void TableView::setComment(
const std::string& comment) { comment_ = comment; }
1786 void TableView::setURIEncodedComment(
const std::string& uriComment) { comment_ = StringMacros::decodeURIComponent(uriComment); }
1789 void TableView::setAuthor(
const std::string& author) { author_ = author; }
1792 void TableView::setCreationTime(time_t t) { creationTime_ = t; }
1795 void TableView::setLastAccessTime(time_t t) { lastAccessTime_ = t; }
1798 void TableView::setLooseColumnMatching(
bool setValue) { fillWithLooseColumnMatching_ = setValue; }
1801 void TableView::reset(
void)
1806 columnsInfo_.clear();
1807 theDataView_.clear();
1811 void TableView::print(std::ostream& out)
const
1813 out <<
"============================================================================="
1816 out <<
"Print: " << tableName_ <<
" Version: " << version_ <<
" Comment: " << comment_ <<
" Author: " << author_
1817 <<
" Creation Time: " << ctime(&creationTime_) << __E__;
1818 out <<
"\t\tNumber of Cols " << getNumberOfColumns() << __E__;
1819 out <<
"\t\tNumber of Rows " << getNumberOfRows() << __E__;
1821 out <<
"Columns:\t";
1822 for (
int i = 0; i < (int)columnsInfo_.size(); ++i)
1823 out << i <<
":" << columnsInfo_[i].getName() <<
":" << columnsInfo_[i].getStorageName() <<
":" << columnsInfo_[i].getType() <<
":"
1824 << columnsInfo_[i].getDataType() <<
"\t ";
1827 out <<
"Rows:" << __E__;
1830 for (
int r = 0; r < (int)getNumberOfRows(); ++r)
1832 out << (int)r <<
":\t";
1833 for (
int c = 0; c < (int)getNumberOfColumns(); ++c)
1835 out << (int)c <<
":";
1838 if (columnsInfo_[c].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
1840 int choiceIndex = -1;
1841 std::vector<std::string> choices = columnsInfo_[c].getDataChoices();
1842 val = StringMacros::convertEnvironmentVariables(theDataView_[r][c]);
1844 if (val == columnsInfo_[c].getDefaultValue())
1848 for (
int i = 0; i < (int)choices.size(); ++i)
1849 if (val == choices[i])
1850 choiceIndex = i + 1;
1853 out <<
"ChoiceIndex=" << choiceIndex <<
":";
1856 out << theDataView_[r][c];
1876 void TableView::printJSON(std::ostream& out)
const
1879 out <<
"\"NAME\" : \"" << tableName_ <<
"\",\n";
1883 out <<
"\"COMMENT\" : ";
1889 for (
unsigned int i = 0; i < val.size(); ++i)
1893 else if (val[i] ==
'\t')
1895 else if (val[i] ==
'\r')
1900 if (val[i] ==
'"' || val[i] ==
'\\')
1907 out <<
"\"AUTHOR\" : \"" << author_ <<
"\",\n";
1908 out <<
"\"CREATION_TIME\" : " << creationTime_ <<
",\n";
1913 out <<
"\"COL_TYPES\" : {\n";
1914 for (
int c = 0; c < (int)getNumberOfColumns(); ++c)
1916 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1917 out <<
"\"" << columnsInfo_[c].getDataType() <<
"\"";
1918 if (c + 1 < (
int)getNumberOfColumns())
1924 out <<
"\"DATA_SET\" : [\n";
1926 for (
int r = 0; r < (int)getNumberOfRows(); ++r)
1929 for (
int c = 0; c < (int)getNumberOfColumns(); ++c)
1931 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1933 out <<
"\"" << getEscapedValueAsString(r, c,
false) <<
"\"";
1935 if (c + 1 < (
int)getNumberOfColumns())
1940 if (r + 1 < (
int)getNumberOfRows())
1952 std::string restoreJSONStringEntities(
const std::string& str)
1954 unsigned int sz = str.size();
1958 std::stringstream retStr;
1960 for (; i < sz - 1; ++i)
1992 retStr << str[sz - 1];
1994 return retStr.str();
2005 int TableView::fillFromJSON(
const std::string& json)
2007 bool dbg = tableName_ ==
"ARTDAQEventBuilderTable" || tableName_ ==
"";
2009 std::map<std::string ,
unsigned int > keyEntryCountMap;
2010 std::vector<std::string> keys;
2011 keys.push_back(
"NAME");
2012 keys.push_back(
"COMMENT");
2013 keys.push_back(
"AUTHOR");
2014 keys.push_back(
"CREATION_TIME");
2016 keys.push_back(
"DATA_SET");
2020 CV_JSON_FILL_COMMENT,
2021 CV_JSON_FILL_AUTHOR,
2022 CV_JSON_FILL_CREATION_TIME,
2024 CV_JSON_FILL_DATA_SET
2027 if(dbg) __COUTV__(tableName_);
2028 if(dbg) __COUTV__(json);
2030 sourceColumnMismatchCount_ = 0;
2031 sourceColumnMissingCount_ = 0;
2032 sourceColumnNames_.clear();
2033 unsigned int colFoundCount = 0;
2035 unsigned int row = -1;
2036 unsigned int colSpeedup = 0;
2037 unsigned int startString, startNumber = 0, endNumber = -1;
2038 unsigned int bracketCount = 0;
2039 unsigned int sqBracketCount = 0;
2044 bool keyIsMatch, keyIsComment;
2045 unsigned int keyIsMatchIndex, keyIsMatchStorageIndex, keyIsMatchCommentIndex;
2046 const std::string COMMENT_ALT_KEY =
"COMMENT";
2048 std::string extractedString =
"", currKey =
"", currVal =
"";
2049 unsigned int currDepth = 0;
2051 std::vector<std::string> jsonPath;
2052 std::vector<char> jsonPathType;
2053 char lastPopType =
'_';
2055 unsigned int matchedKey = -1;
2056 unsigned int lastCol = -1;
2059 for (; i < json.size(); ++i)
2064 if (i - 1 < json.size() &&
2065 json[i - 1] ==
'\\')
2068 inQuotes = !inQuotes;
2073 extractedString = restoreJSONStringEntities(json.substr(startString + 1, i - startString - 1));
2082 if (jsonPathType[jsonPathType.size() - 1] !=
'{' || !newString)
2084 __COUT__ <<
"Invalid ':' position" << __E__;
2089 jsonPathType.push_back(
'K');
2090 jsonPath.push_back(extractedString);
2109 if (lastPopType ==
'{')
2112 if (jsonPathType[jsonPathType.size() - 1] ==
'K')
2115 jsonPath.pop_back();
2116 jsonPathType.pop_back();
2122 currVal = extractedString;
2125 if (endNumber == (
unsigned int)-1 ||
2126 endNumber <= startNumber)
2129 if (endNumber <= startNumber)
2132 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
2135 currDepth = bracketCount;
2137 if (jsonPathType[jsonPathType.size() - 1] ==
'K')
2139 currKey = jsonPath[jsonPathType.size() - 1];
2144 jsonPath.pop_back();
2145 jsonPathType.pop_back();
2147 else if (jsonPathType[jsonPathType.size() - 1] ==
'[')
2150 for (
unsigned int k = jsonPathType.size() - 2; k < jsonPathType.size(); --k)
2151 if (jsonPathType[k] ==
'K')
2153 currKey = jsonPath[k];
2158 __COUT__ <<
"Invalid array position" << __E__;
2167 __COUT__ <<
"Invalid ',' position" << __E__;
2178 jsonPathType.push_back(
'{');
2179 jsonPath.push_back(
"{");
2192 if (lastPopType !=
'{' &&
2193 jsonPathType[jsonPathType.size() - 1] ==
'K')
2195 currDepth = bracketCount;
2196 currKey = jsonPath[jsonPathType.size() - 1];
2198 currVal = extractedString;
2201 if (endNumber == (
unsigned int)-1 ||
2202 endNumber <= startNumber)
2205 if (endNumber <= startNumber)
2208 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
2212 jsonPath.pop_back();
2213 jsonPathType.pop_back();
2216 if (jsonPathType[jsonPathType.size() - 1] !=
'{')
2218 __COUT__ <<
"Invalid '}' position" << __E__;
2222 jsonPath.pop_back();
2223 jsonPathType.pop_back();
2229 jsonPathType.push_back(
'[');
2230 jsonPath.push_back(
"[");
2239 if (jsonPathType[jsonPathType.size() - 1] !=
'[')
2241 __COUT__ <<
"Invalid ']' position" << __E__;
2245 currDepth = bracketCount;
2249 currVal = extractedString;
2252 if (endNumber == (
unsigned int)-1 ||
2253 endNumber <= startNumber)
2256 if (endNumber <= startNumber)
2259 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
2264 for (
unsigned int k = jsonPathType.size() - 2; k < jsonPathType.size(); --k)
2265 if (jsonPathType[k] ==
'K')
2267 currKey = jsonPath[k];
2272 __COUT__ <<
"Invalid array position" << __E__;
2277 if (jsonPathType[jsonPathType.size() - 1] !=
'[')
2279 __COUT__ <<
"Invalid ']' position" << __E__;
2283 jsonPath.pop_back();
2284 jsonPathType.pop_back();
2293 if (startNumber != (
unsigned int)-1 && endNumber == (
unsigned int)-1)
2305 if (0 && tableName_ ==
"ARTDAQ_DATALOGGER_TABLE")
2307 std::cout << i <<
":\t" << json[i] <<
" - ";
2317 std::cout <<
"ExtKey=";
2318 for (
unsigned int k = 0; k < jsonPath.size(); ++k)
2319 std::cout << jsonPath[k] <<
"/";
2321 std::cout << lastPopType <<
" ";
2322 std::cout << bracketCount <<
" ";
2323 std::cout << sqBracketCount <<
" ";
2324 std::cout << inQuotes <<
" ";
2325 std::cout << newValue <<
"-";
2326 std::cout << currKey <<
"-{" << currDepth <<
"}:";
2327 std::cout << currVal <<
" ";
2328 std::cout << startNumber <<
"-";
2329 std::cout << endNumber <<
" ";
2331 __COUTV__(fillWithLooseColumnMatching_);
2340 for (
unsigned int k = 0; k < keys.size(); ++k)
2341 if ((currDepth == 1 && keys[k] == currKey) || (currDepth > 1 && keys[k] == jsonPath[1]))
2344 if (matchedKey != (
unsigned int)-1)
2351 case CV_JSON_FILL_NAME:
2357 if(currVal != getTableName() && getTableName() !=
"TABLE_GROUP_METADATA")
2358 __COUT_WARN__ <<
"JSON-fill Table name mismatch: " <<
2359 currVal <<
" vs " <<
2360 getTableName() << __E__;
2363 case CV_JSON_FILL_COMMENT:
2365 setComment(currVal);
2367 case CV_JSON_FILL_AUTHOR:
2371 case CV_JSON_FILL_CREATION_TIME:
2373 setCreationTime(strtol(currVal.c_str(), 0, 10));
2378 case CV_JSON_FILL_DATA_SET:
2390 unsigned int col, ccnt = 0;
2391 unsigned int noc = getNumberOfColumns();
2392 for (; ccnt < noc; ++ccnt)
2398 if (fillWithLooseColumnMatching_)
2411 if (getNumberOfRows() == 1)
2412 sourceColumnNames_.emplace(currKey);
2416 if (row >= getNumberOfRows())
2418 __SS__ <<
"Invalid row" << __E__;
2419 std::cout << ss.str();
2424 theDataView_[row][col] = currVal;
2431 col = (ccnt + colSpeedup) % noc;
2437 keyIsComment =
true;
2438 for (keyIsMatchIndex = 0, keyIsMatchStorageIndex = 0, keyIsMatchCommentIndex = 0; keyIsMatchIndex < currKey.size();
2441 if (columnsInfo_[col].getStorageName()[keyIsMatchStorageIndex] ==
'_')
2442 ++keyIsMatchStorageIndex;
2444 if (currKey[keyIsMatchIndex] ==
'_')
2448 if (keyIsMatchStorageIndex >= columnsInfo_[col].getStorageName().size() ||
2449 currKey[keyIsMatchIndex] != columnsInfo_[col].getStorageName()[keyIsMatchStorageIndex])
2458 if (keyIsComment && keyIsMatchCommentIndex < COMMENT_ALT_KEY.size())
2460 if (currKey[keyIsMatchIndex] != COMMENT_ALT_KEY[keyIsMatchCommentIndex])
2463 keyIsComment =
false;
2467 ++keyIsMatchStorageIndex;
2470 if (keyIsMatch || keyIsComment)
2473 if (keyEntryCountMap.find(currKey) == keyEntryCountMap.end())
2474 keyEntryCountMap[currKey] = 0;
2476 ++keyEntryCountMap.at(currKey);
2479 if (keyEntryCountMap.size() == 1 ||
2480 (keyEntryCountMap.at(currKey) && keyEntryCountMap.at(currKey) > row))
2482 if (getNumberOfRows())
2483 sourceColumnMissingCount_ += getNumberOfColumns() - colFoundCount;
2491 if (getNumberOfRows() == 1)
2492 sourceColumnNames_.emplace(currKey);
2496 if (row >= getNumberOfRows())
2498 __SS__ <<
"Invalid row" << __E__;
2499 __COUT__ <<
"\n" << ss.str();
2504 theDataView_[row][col] = currVal;
2510 if (ccnt >= getNumberOfColumns())
2512 __COUT__ <<
"Invalid column in JSON source data: " << currKey <<
" not found in column names of table named " << getTableName()
2517 ++sourceColumnMismatchCount_;
2518 if (getNumberOfRows() == 1)
2519 sourceColumnNames_.emplace(currKey);
2522 __COUT_WARN__ <<
"Trying to ignore error, and not populating "
2527 colSpeedup = (colSpeedup + 1) % noc;
2549 if (!fillWithLooseColumnMatching_ && sourceColumnMissingCount_ > 0)
2551 const std::set<std::string> srcColNames = getSourceColumnNames();
2552 __SS__ <<
"Can not ignore errors because not every column was found in the "
2554 <<
". Please see the details below:\n\n"
2555 <<
"The source column size was found to be " << srcColNames.size() <<
", and the current number of columns for this table is "
2556 << getNumberOfColumns() <<
". This resulted in a count of " << getSourceColumnMismatch() <<
" source column mismatches, and a count of "
2557 << getSourceColumnMissing() <<
" table entries missing in " << getNumberOfRows() <<
" row(s) of data." << __E__;
2559 ss <<
"\n\nSource column names in ALPHABETICAL order were as follows:\n";
2561 std::string preIndexStr =
"";
2562 for (
auto& srcColName : srcColNames)
2564 ss <<
"\n\t" << preIndexStr << index <<
". " << srcColName;
2575 std::set<std::string> destColNames = getColumnStorageNames();
2576 ss <<
"\n\nCurrent table column names in ALPHABETICAL order are as follows:\n";
2579 for (
auto& destColName : destColNames)
2581 ss <<
"\n\t" << preIndexStr << index <<
". " << destColName;
2591 ss << StringMacros::stackTrace();
2601 bool TableView::isURIEncodedCommentTheSame(
const std::string& comment)
const
2603 std::string compareStr = StringMacros::decodeURIComponent(comment);
2604 return comment_ == compareStr;
2663 int TableView::fillFromCSV(
const std::string& data,
const int& dataOffset,
const std::string& author)
2671 int j = data.find(
',', i);
2672 int k = data.find(
';', i);
2674 bool rowWasModified;
2675 unsigned int countRowsModified = 0;
2676 int authorCol = findColByType(TableViewColumnInfo::TYPE_AUTHOR);
2677 int timestampCol = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
2680 while (k != (
int)(std::string::npos))
2682 rowWasModified =
false;
2683 if (r >= (
int)getNumberOfRows())
2687 rowWasModified =
true;
2690 while (j < k && j != (
int)(std::string::npos))
2695 if (c >= (
int)getNumberOfColumns() - 2)
2698 j = data.find(
',', i);
2703 if (setURIEncodedValue(data.substr(i, j - i), r, c))
2704 rowWasModified =
true;
2707 j = data.find(
',', i);
2712 if (author !=
"" && rowWasModified)
2714 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << __E__;
2715 setValue(author, r, authorCol);
2716 setValue(time(0), r, timestampCol);
2720 ++countRowsModified;
2726 j = data.find(
',', i);
2727 k = data.find(
';', i);
2731 while (r < (
int)getNumberOfRows())
2734 __COUT__ <<
"Row deleted: " << (int)r << __E__;
2735 ++countRowsModified;
2738 __COUT_INFO__ <<
"countRowsModified=" << countRowsModified << __E__;
2740 if (!countRowsModified)
2745 bool match = getColumnStorageNames().size() == getSourceColumnNames().size();
2748 for (
auto& destColName : getColumnStorageNames())
2749 if (getSourceColumnNames().find(destColName) == getSourceColumnNames().end())
2751 __COUT__ <<
"Found column name mismach for '" << destColName <<
"'... So allowing same data!" << __E__;
2760 __SS__ <<
"No rows were modified! No reason to fill a view with same content." << __E__;
2761 __COUT__ <<
"\n" << ss.str();
2771 sourceColumnNames_.clear();
2772 for (
unsigned int i = 0; i < getNumberOfColumns(); ++i)
2773 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
2794 bool TableView::setURIEncodedValue(
const std::string& value,
const unsigned int& r,
const unsigned int& c,
const std::string& author)
2796 if (!(c < columnsInfo_.size() && r < getNumberOfRows()))
2798 __SS__ <<
"Invalid row (" << (int)r <<
") col (" << (
int)c << ") requested!"
2799 << "Number of Rows = " << getNumberOfRows() << "Number of Columns = " << columnsInfo_.size() << __E__;
2804 std::
string valueStr =
StringMacros::decodeURIComponent(value);
2805 std::
string originalValueStr = getValueAsString(r, c, false);
2813 std::string convertedString = StringMacros::convertEnvironmentVariables(valueStr);
2828 theDataView_[r][c] = valueStr;
2830 else if (columnsInfo_[c].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
2842 setValue(time_t(strtol(valueStr.c_str(), 0, 10)), r, c);
2845 theDataView_[r][c] = valueStr;
2847 bool rowWasModified = (originalValueStr != getValueAsString(r, c,
false));
2850 if (author !=
"" && rowWasModified)
2852 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << __E__;
2853 int authorCol = findColByType(TableViewColumnInfo::TYPE_AUTHOR);
2854 int timestampCol = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
2855 setValue(author, r, authorCol);
2856 setValue(time(0), r, timestampCol);
2859 return rowWasModified;
2863 void TableView::resizeDataView(
unsigned int nRows,
unsigned int nCols)
2867 theDataView_.resize(nRows, std::vector<std::string>(nCols));
2877 unsigned int TableView::addRow(
const std::string& author,
2878 unsigned char incrementUniqueData ,
2881 const std::string& baseNameAutoUID ,
2882 unsigned int rowToAdd )
2885 if (rowToAdd == (
unsigned int)-1)
2886 rowToAdd = getNumberOfRows();
2888 theDataView_.resize(getNumberOfRows() + 1, std::vector<std::string>(getNumberOfColumns()));
2891 for (
unsigned int r = getNumberOfRows() - 2; r >= rowToAdd; --r)
2893 if (r == (
unsigned int)-1)
2895 for (
unsigned int col = 0; col < getNumberOfColumns(); ++col)
2896 theDataView_[r + 1][col] = theDataView_[r][col];
2899 std::vector<std::string> defaultRowValues = getDefaultRowValues();
2902 std::string tmpString, baseString;
2906 std::string numString;
2911 for (
unsigned int col = 0; col < getNumberOfColumns(); ++col)
2918 if (incrementUniqueData &&
2919 (col == getColUID() || (getNumberOfRows() > 1 && (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_DATA ||
2920 columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA))))
2922 if (col == getColUID())
2923 setUniqueColumnValue(rowToAdd, col, baseNameAutoUID );
2925 setUniqueColumnValue(rowToAdd, col);
3008 theDataView_[rowToAdd][col] = defaultRowValues[col];
3013 __COUT__ <<
"Row=" << rowToAdd <<
" was created!" << __E__;
3015 int authorCol = findColByType(TableViewColumnInfo::TYPE_AUTHOR);
3016 int timestampCol = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
3017 setValue(author, rowToAdd, authorCol);
3018 setValue(time(0), rowToAdd, timestampCol);
3027 void TableView::deleteRow(
int r)
3029 if (r >= (
int)getNumberOfRows())
3032 __SS__ <<
"Row " << (int)r <<
" is out of bounds (Row Count = " << getNumberOfRows() <<
") and can not be deleted." << __E__;
3036 theDataView_.erase(theDataView_.begin() + r);
3055 bool TableView::getChildLink(
const unsigned int& c,
bool& isGroup, std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>& linkPair)
const
3057 if (!(c < columnsInfo_.size()))
3059 __SS__ <<
"Invalid col (" << (int)c <<
") requested for child link!" << __E__;
3067 if ((isGroup = columnsInfo_[c].isChildLinkGroupID()) || columnsInfo_[c].isChildLinkUID())
3071 linkPair.second = c;
3072 std::string index = columnsInfo_[c].getChildLinkIndex();
3077 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
3083 else if (columnsInfo_[col].isChildLink() && index == columnsInfo_[col].getChildLinkIndex())
3088 linkPair.first = col;
3094 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find complete child link for column name " << columnsInfo_[c].getName() << __E__;
3098 if (!columnsInfo_[c].isChildLink())
3103 std::string index = columnsInfo_[c].getChildLinkIndex();
3108 for (
unsigned int col = 0; col < columnsInfo_.size(); ++col)
3125 if (((columnsInfo_[col].isChildLinkUID() && !(isGroup =
false)) || (columnsInfo_[col].isChildLinkGroupID() && (isGroup =
true))) &&
3126 index == columnsInfo_[col].getChildLinkIndex())
3131 linkPair.second = col;
3137 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find complete child link id for column name " << columnsInfo_[c].getName() << __E__;