1 #include "otsdaq/TableCore/TableView.h"
11 #define __MF_SUBJECT__ "TableView"
13 #define __COUT_HDR__ (std::string(":") + tableName_ + "v" + version_.toString() + ":\t")
15 const unsigned int TableView::INVALID = -1;
18 TableView::TableView(
const std::string& name)
19 : uniqueStorageIdentifier_(
"")
24 , creationTime_(time(0))
28 , colPriority_(INVALID)
29 , fillWithLooseColumnMatching_(false)
30 , sourceColumnMismatchCount_(0)
31 , sourceColumnMissingCount_(0)
36 TableView::~TableView(
void) {}
44 __SS__ <<
"Invalid use of operator=... Should not directly copy a TableView. Please "
45 "use TableView::copy(sourceView,author,comment)";
52 const std::string& author)
54 tableName_ = src.tableName_;
55 version_ = destinationVersion;
56 comment_ = src.comment_;
59 lastAccessTime_ = time(0);
60 columnsInfo_ = src.columnsInfo_;
61 theDataView_ = src.theDataView_;
62 sourceColumnNames_ = src.sourceColumnNames_;
90 unsigned int TableView::copyRows(
const std::string& author,
92 unsigned int srcOffsetRow,
93 unsigned int srcRowsToCopy,
94 unsigned int destOffsetRow,
95 bool generateUniqueDataColumns)
101 unsigned int retRow = (
unsigned int)-1;
104 if(src.getNumberOfColumns() != getNumberOfColumns())
106 __SS__ <<
"Error! Number of Columns of source view must match destination view."
107 <<
"Dimension of source is [" << src.getNumberOfColumns()
108 <<
"] and of destination is [" << getNumberOfColumns() <<
"]." << __E__;
112 unsigned int srcRows = src.getNumberOfRows();
114 for(
unsigned int r = 0; r < srcRowsToCopy; ++r)
116 if(r + srcOffsetRow >= srcRows)
119 destOffsetRow = addRow(author,
120 generateUniqueDataColumns ,
124 if(retRow == (
unsigned int)-1)
125 retRow = destOffsetRow;
128 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
129 if(generateUniqueDataColumns &&
130 (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_DATA ||
131 columnsInfo_[col].getType() ==
132 TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA))
135 theDataView_[destOffsetRow][col] =
136 src.theDataView_[r + srcOffsetRow][col];
152 void TableView::init(
void)
160 std::set<std::string> colNameSet;
161 std::string capsColName, colName;
162 for(
auto& colInfo : columnsInfo_)
164 colName = colInfo.getStorageName();
165 if(colName ==
"COMMENT_DESCRIPTION")
168 for(
unsigned int i = 0; i < colName.size(); ++i)
170 if(colName[i] ==
'_')
172 capsColName += colName[i];
175 colNameSet.emplace(capsColName);
178 if(colNameSet.size() != columnsInfo_.size())
180 __SS__ <<
"Table Error:\t"
181 <<
" Columns names must be unique! There are " << columnsInfo_.size()
182 <<
" columns and the unique name count is " << colNameSet.size()
205 if((colPos = findColByType(TableViewColumnInfo::TYPE_COMMENT)) != INVALID)
207 if(columnsInfo_[colPos].getName() != TableViewColumnInfo::COL_NAME_COMMENT)
209 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
210 <<
" data type column must have name="
211 << TableViewColumnInfo::COL_NAME_COMMENT << __E__;
215 if(findColByType(TableViewColumnInfo::TYPE_COMMENT, colPos + 1) !=
218 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
219 <<
" data type in column " << columnsInfo_[colPos].getName()
220 <<
" is repeated. This is not allowed." << __E__;
224 if(colPos != getNumberOfColumns() - 3)
226 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
227 <<
" data type column must be 3rd to last (in column "
228 << getNumberOfColumns() - 3 <<
")." << __E__;
234 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
235 <<
" data type column "
236 <<
" is missing. This is not allowed." << __E__;
241 if((colPos = findColByType(TableViewColumnInfo::TYPE_AUTHOR)) != INVALID)
243 if(findColByType(TableViewColumnInfo::TYPE_AUTHOR, colPos + 1) !=
246 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR
247 <<
" data type in column " << columnsInfo_[colPos].getName()
248 <<
" is repeated. This is not allowed." << __E__;
252 if(colPos != getNumberOfColumns() - 2)
254 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR
255 <<
" data type column must be 2nd to last (in column "
256 << getNumberOfColumns() - 2 <<
")." << __E__;
262 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR
263 <<
" data type column "
264 <<
" is missing. This is not allowed." << __E__;
269 if((colPos = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP)) != INVALID)
271 if(findColByType(TableViewColumnInfo::TYPE_TIMESTAMP, colPos + 1) !=
274 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP
275 <<
" data type in column " << columnsInfo_[colPos].getName()
276 <<
" is repeated. This is not allowed." << __E__;
280 if(colPos != getNumberOfColumns() - 1)
282 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP
283 <<
" data type column must be last (in column "
284 << getNumberOfColumns() - 1 <<
")." << __E__;
285 __COUT_ERR__ <<
"\n" << ss.str();
291 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP
292 <<
" data type column "
293 <<
" is missing. This is not allowed." << __E__;
300 std::set<std::string > uidSet;
301 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
303 if(uidSet.find(theDataView_[row][colUID_]) != uidSet.end())
305 __SS__ << (
"Entries in UID are not unique. Specifically at row=" +
306 std::to_string(row) +
" value=" + theDataView_[row][colUID_])
311 if(theDataView_[row][colUID_].size() == 0)
313 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' "
314 <<
" was identified. UIDs must contain at least 1 character."
319 for(
unsigned int i = 0; i < theDataView_[row][colUID_].size(); ++i)
320 if(!((theDataView_[row][colUID_][i] >=
'A' &&
321 theDataView_[row][colUID_][i] <=
'Z') ||
322 (theDataView_[row][colUID_][i] >=
'a' &&
323 theDataView_[row][colUID_][i] <=
'z') ||
324 (theDataView_[row][colUID_][i] >=
'0' &&
325 theDataView_[row][colUID_][i] <=
'9') ||
326 (theDataView_[row][colUID_][i] ==
'-' ||
327 theDataView_[row][colUID_][i] <=
'_')))
329 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' "
330 <<
" was identified. UIDs must contain only letters, numbers,"
331 <<
"dashes, and underscores." << __E__;
335 uidSet.insert(theDataView_[row][colUID_]);
337 if(uidSet.size() != getNumberOfRows())
339 __SS__ <<
"Entries in UID are not unique!"
340 <<
"There are " << getNumberOfRows()
341 <<
" records and the unique UID count is " << uidSet.size() << __E__;
346 colPos = (
unsigned int)-1;
347 while((colPos = findColByType(TableViewColumnInfo::TYPE_UNIQUE_DATA,
348 colPos + 1)) != INVALID)
350 std::set<std::string > uDataSet;
351 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
353 if(uDataSet.find(theDataView_[row][colPos]) != uDataSet.end())
355 __SS__ <<
"Entries in Unique Data column "
356 << columnsInfo_[colPos].getName()
357 << (
" are not unique. Specifically at row=" +
358 std::to_string(row) +
359 " value=" + theDataView_[row][colPos])
363 uDataSet.insert(theDataView_[row][colPos]);
365 if(uDataSet.size() != getNumberOfRows())
367 __SS__ <<
"Entries in Unique Data column "
368 << columnsInfo_[colPos].getName() <<
" are not unique!"
369 <<
"There are " << getNumberOfRows()
370 <<
" records and the unique data count is " << uDataSet.size()
378 colPos = (
unsigned int)-1;
379 while((colPos = findColByType(TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA,
380 colPos + 1)) != INVALID)
385 for(
unsigned int groupIdColPos = 0; groupIdColPos < columnsInfo_.size();
387 if(columnsInfo_[groupIdColPos].isGroupID())
389 std::map<std::string ,
390 std::pair<
unsigned int ,
391 std::set<std::string > > >
394 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
396 auto groupIds = getSetOfGroupIDs(groupIdColPos, row);
398 for(
const auto& groupId : groupIds)
400 uGroupDataSets[groupId].first++;
402 if(uGroupDataSets[groupId].second.find(
403 theDataView_[row][colPos]) !=
404 uGroupDataSets[groupId].second.end())
406 __SS__ <<
"Entries in Unique Group Data column " << colPos
407 <<
":" << columnsInfo_[colPos].getName()
408 <<
" are not unique for group ID '" << groupId
409 <<
".' Specifically at row=" << std::to_string(row)
410 <<
" value=" << theDataView_[row][colPos] << __E__;
413 uGroupDataSets[groupId].second.insert(
414 theDataView_[row][colPos]);
418 for(
const auto& groupPair : uGroupDataSets)
419 if(uGroupDataSets[groupPair.first].second.size() !=
420 uGroupDataSets[groupPair.first].first)
423 <<
"Entries in Unique Data column "
424 << columnsInfo_[colPos].getName()
425 <<
" are not unique for group '" << groupPair.first
427 <<
"There are " << uGroupDataSets[groupPair.first].first
428 <<
" records and the unique data count is "
429 << uGroupDataSets[groupPair.first].second.size() << __E__;
435 auto rowDefaults = getDefaultRowValues();
442 std::set<std::string> groupIdIndexes, childLinkIndexes, childLinkIdLabels;
443 unsigned int groupIdIndexesCount = 0, childLinkIndexesCount = 0,
444 childLinkIdLabelsCount = 0;
446 std::pair<
unsigned int ,
unsigned int > tmpLinkPair;
448 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
450 if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
452 const std::vector<std::string>& theDataChoices =
453 columnsInfo_[col].getDataChoices();
456 if(theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=1")
460 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
464 if(theDataView_[row][col] == rowDefaults[col])
467 for(
const auto& choice : theDataChoices)
469 if(theDataView_[row][col] == choice)
477 __SS__ << getTableName() <<
" Error:\t'" << theDataView_[row][col]
478 <<
"' in column " << columnsInfo_[col].getName()
479 <<
" is not a valid Fixed Choice option. "
480 <<
"Possible values are as follows: ";
482 for(
unsigned int i = 0;
483 i < columnsInfo_[col].getDataChoices().size();
488 ss << columnsInfo_[col].getDataChoices()[i];
495 else if(columnsInfo_[col].isChildLink())
499 const std::vector<std::string>& theDataChoices =
500 columnsInfo_[col].getDataChoices();
503 if(!theDataChoices.size() || theDataChoices[0] ==
"arbitraryBool=1")
508 (theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=0");
512 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
517 for(
const auto& choice : theDataChoices)
519 if(skipOne && !hasSkipped)
525 if(theDataView_[row][col] == choice)
533 __SS__ << getTableName() <<
" Error:\t the value '"
534 << theDataView_[row][col] <<
"' in column "
535 << columnsInfo_[col].getName()
536 <<
" is not a valid Fixed Choice option. "
537 <<
"Possible values are as follows: ";
542 for(
unsigned int i = skipOne ? 1 : 0;
543 i < columnsInfo_[col].getDataChoices().size();
546 if(i > (skipOne ? 1 : 0))
548 ss << columnsInfo_[col].getDataChoices()[i];
555 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_ON_OFF)
556 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
558 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" ||
559 theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
560 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_ON;
561 else if(theDataView_[row][col] ==
"0" ||
562 theDataView_[row][col] ==
"off" ||
563 theDataView_[row][col] ==
"Off" ||
564 theDataView_[row][col] ==
"OFF")
565 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_OFF;
568 __SS__ << getTableName() <<
" Error:\t the value '"
569 << theDataView_[row][col] <<
"' in column "
570 << columnsInfo_[col].getName()
571 <<
" is not a valid Type (On/Off) std::string. Possible "
572 "values are 1, on, On, ON, 0, off, Off, OFF."
577 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_TRUE_FALSE)
578 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
580 if(theDataView_[row][col] ==
"1" ||
581 theDataView_[row][col] ==
"true" ||
582 theDataView_[row][col] ==
"True" ||
583 theDataView_[row][col] ==
"TRUE")
584 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_TRUE;
585 else if(theDataView_[row][col] ==
"0" ||
586 theDataView_[row][col] ==
"false" ||
587 theDataView_[row][col] ==
"False" ||
588 theDataView_[row][col] ==
"FALSE")
589 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_FALSE;
592 __SS__ << getTableName() <<
" Error:\t the value '"
593 << theDataView_[row][col] <<
"' in column "
594 << columnsInfo_[col].getName()
595 <<
" is not a valid Type (True/False) std::string. "
596 "Possible values are 1, true, True, TRUE, 0, false, "
602 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_YES_NO)
603 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
605 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" ||
606 theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
607 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_YES;
608 else if(theDataView_[row][col] ==
"0" ||
609 theDataView_[row][col] ==
"no" ||
610 theDataView_[row][col] ==
"No" ||
611 theDataView_[row][col] ==
"NO")
612 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_NO;
615 __SS__ << getTableName() <<
" Error:\t the value '"
616 << theDataView_[row][col] <<
"' in column "
617 << columnsInfo_[col].getName()
618 <<
" is not a valid Type (Yes/No) std::string. Possible "
619 "values are 1, yes, Yes, YES, 0, no, No, NO."
624 else if(columnsInfo_[col].isGroupID())
626 colLinkGroupIDs_[columnsInfo_[col].getChildLinkIndex()] =
629 groupIdIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
630 ++groupIdIndexesCount;
632 else if(columnsInfo_[col].isChildLink())
635 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
636 if(theDataView_[row][col] ==
"NoLink" ||
637 theDataView_[row][col] ==
"No_Link" ||
638 theDataView_[row][col] ==
"NOLINK" ||
639 theDataView_[row][col] ==
"NO_LINK" ||
640 theDataView_[row][col] ==
"Nolink" ||
641 theDataView_[row][col] ==
"nolink" ||
642 theDataView_[row][col] ==
"noLink")
643 theDataView_[row][col] =
644 TableViewColumnInfo::DATATYPE_LINK_DEFAULT;
647 childLinkIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
648 ++childLinkIndexesCount;
651 if(columnsInfo_[col].getDataType() !=
652 TableViewColumnInfo::DATATYPE_STRING)
654 __SS__ << getTableName() <<
" Error:\t"
655 <<
"Column " << col <<
" with name '"
656 << columnsInfo_[col].getName()
657 <<
"' is a Child Link column and has an illegal data type of '"
658 << columnsInfo_[col].getDataType()
659 <<
"'. The data type for Child Link columns must be "
660 << TableViewColumnInfo::DATATYPE_STRING << __E__;
665 getChildLink(col, tmpIsGroup, tmpLinkPair);
667 else if(columnsInfo_[col].isChildLinkUID() ||
668 columnsInfo_[col].isChildLinkGroupID())
671 childLinkIdLabels.emplace(columnsInfo_[col].getChildLinkIndex());
672 ++childLinkIdLabelsCount;
675 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
676 if(theDataView_[row][col] ==
"")
677 theDataView_[row][col] = rowDefaults[col];
680 getChildLink(col, tmpIsGroup, tmpLinkPair);
685 if(groupIdIndexes.size() != groupIdIndexesCount)
687 __SS__ << (
"GroupId Labels are not unique!") <<
"There are "
688 << groupIdIndexesCount <<
" GroupId Labels and the unique count is "
689 << groupIdIndexes.size() << __E__;
692 if(childLinkIndexes.size() != childLinkIndexesCount)
694 __SS__ << (
"Child Link Labels are not unique!") <<
"There are "
695 << childLinkIndexesCount
696 <<
" Child Link Labels and the unique count is "
697 << childLinkIndexes.size() << __E__;
700 if(childLinkIdLabels.size() != childLinkIdLabelsCount)
702 __SS__ << (
"Child Link ID Labels are not unique!") <<
"There are "
703 << childLinkIdLabelsCount
704 <<
" Child Link ID Labels and the unique count is "
705 << childLinkIdLabels.size() << __E__;
711 __COUT__ <<
"Error occured in TableView::init() for version=" << version_
722 void TableView::getValue(std::string& value,
725 bool doConvertEnvironmentVariables)
const
727 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
729 __SS__ <<
"Invalid row col requested" << __E__;
733 value = validateValueForColumn(
734 theDataView_[row][col], col, doConvertEnvironmentVariables);
742 std::string TableView::validateValueForColumn(
const std::string& value,
744 bool doConvertEnvironmentVariables)
const
746 if(col >= columnsInfo_.size())
748 __SS__ <<
"Invalid col requested" << __E__;
752 if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA &&
753 value == columnsInfo_[col].getDefaultValue())
757 std::vector<std::string> choices = columnsInfo_[col].getDataChoices();
760 bool skipOne = (choices.size() && choices[0].find(
"arbitraryBool=") == 0);
761 size_t index = (skipOne ? 1 : 0);
762 if(choices.size() > index)
764 return doConvertEnvironmentVariables
765 ? StringMacros::convertEnvironmentVariables(choices[index])
770 if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_STRING)
771 return doConvertEnvironmentVariables
772 ? StringMacros::convertEnvironmentVariables(value)
774 else if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
776 return StringMacros::getTimestampString(
777 doConvertEnvironmentVariables
778 ? StringMacros::convertEnvironmentVariables(value)
792 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
793 <<
" in configuration " << tableName_
794 <<
" at column=" << columnsInfo_[col].getName()
795 <<
" for getValue with type '"
796 << StringMacros::demangleTypeName(
typeid(std::string).name()) <<
"'"
808 std::string TableView::getValueAsString(
unsigned int row,
810 bool doConvertEnvironmentVariables)
const
812 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
814 __SS__ << (
"Invalid row col requested") << __E__;
820 if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_ON_OFF)
822 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" ||
823 theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
824 return TableViewColumnInfo::TYPE_VALUE_ON;
826 return TableViewColumnInfo::TYPE_VALUE_OFF;
828 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_TRUE_FALSE)
830 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" ||
831 theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
832 return TableViewColumnInfo::TYPE_VALUE_TRUE;
834 return TableViewColumnInfo::TYPE_VALUE_FALSE;
836 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_YES_NO)
838 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" ||
839 theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
840 return TableViewColumnInfo::TYPE_VALUE_YES;
842 return TableViewColumnInfo::TYPE_VALUE_NO;
846 return doConvertEnvironmentVariables
847 ? StringMacros::convertEnvironmentVariables(theDataView_[row][col])
848 : theDataView_[row][col];
857 std::string TableView::getEscapedValueAsString(
unsigned int row,
859 bool doConvertEnvironmentVariables)
const
861 std::string val = getValueAsString(row, col, doConvertEnvironmentVariables);
862 std::string retVal =
"";
863 retVal.reserve(val.size());
864 for(
unsigned int i = 0; i < val.size(); ++i)
868 else if(val[i] ==
'\t')
870 else if(val[i] ==
'\r')
875 if(val[i] ==
'"' || val[i] ==
'\\')
886 void TableView::setValue(
const std::string& value,
unsigned int row,
unsigned int col)
888 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
890 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
894 if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_STRING)
895 theDataView_[row][col] = value;
899 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
900 <<
" in configuration " << tableName_
901 <<
" at column=" << columnsInfo_[col].getName()
902 <<
" for setValue with type '"
903 << StringMacros::demangleTypeName(
typeid(value).name()) <<
"'" << __E__;
907 void TableView::setValue(
const char* value,
unsigned int row,
unsigned int col)
909 setValue(std::string(value), row, col);
915 void TableView::setValueAsString(
const std::string& value,
919 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
921 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
925 theDataView_[row][col] = value;
931 const unsigned int TableView::initColUID(
void)
933 if(colUID_ != INVALID)
937 colUID_ = findColByType(TableViewColumnInfo::TYPE_UID);
938 if(colUID_ == INVALID)
940 __COUT__ <<
"Column Types: " << __E__;
941 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
942 std::cout << columnsInfo_[col].getType() <<
"() "
943 << columnsInfo_[col].getName() << __E__;
944 __SS__ <<
"\tMissing UID Column in table named '" << tableName_ <<
"'" << __E__;
953 const unsigned int TableView::getColUID(
void)
const
955 if(colUID_ != INVALID)
958 __COUT__ <<
"Column Types: " << __E__;
959 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
960 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
963 __SS__ << (
"Missing UID Column in config named " + tableName_ +
964 ". (Possibly TableView was just not initialized?" +
965 " This is the const call so can not alter class members)")
968 ss << StringMacros::stackTrace() << __E__;
976 const unsigned int TableView::initColStatus(
void)
978 if(colStatus_ != INVALID)
982 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
983 if(columnsInfo_[col].getName() == TableViewColumnInfo::COL_NAME_STATUS)
988 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
989 if(columnsInfo_[col].getName() == TableViewColumnInfo::COL_NAME_ENABLED)
997 __SS__ <<
"\tMissing column named '" << TableViewColumnInfo::COL_NAME_STATUS
998 <<
"' or '" << TableViewColumnInfo::COL_NAME_ENABLED <<
"' in table '"
999 << tableName_ <<
".'" << __E__;
1000 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1001 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1002 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1012 const unsigned int TableView::initColPriority(
void)
1014 if(colPriority_ != INVALID)
1015 return colPriority_;
1019 findCol(
"*" + TableViewColumnInfo::COL_NAME_PRIORITY);
1020 if(colPriority_ == INVALID)
1022 __SS__ <<
"\tMissing column named '" << TableViewColumnInfo::COL_NAME_PRIORITY
1023 <<
"' in table '" << tableName_ <<
".'" << __E__;
1024 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1025 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1026 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1031 return colPriority_;
1038 const unsigned int TableView::getColStatus(
void)
const
1040 if(colStatus_ != INVALID)
1043 __SS__ <<
"\tMissing column named '" << TableViewColumnInfo::COL_NAME_STATUS
1044 <<
"' or '" << TableViewColumnInfo::COL_NAME_ENABLED <<
"' in table '"
1045 << tableName_ <<
".'"
1046 <<
" (The Status column is identified when the TableView is initialized)"
1049 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1050 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1051 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1056 ss << StringMacros::stackTrace() << __E__;
1068 const unsigned int TableView::getColPriority(
void)
const
1070 if(colPriority_ != INVALID)
1071 return colPriority_;
1073 __SS__ <<
"Priority column was not found... \nColumn Types: " << __E__;
1075 ss <<
"Missing " << TableViewColumnInfo::COL_NAME_PRIORITY
1076 <<
" Column in table named '" << tableName_
1077 <<
".' (The Priority column is identified when the TableView is initialized)"
1081 ss <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
1082 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1083 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1087 ss << StringMacros::stackTrace() << __E__;
1095 void TableView::addRowToGroup(
1096 const unsigned int& row,
1097 const unsigned int& col,
1098 const std::string& groupID)
1101 if(isEntryInGroupCol(row, col, groupID))
1103 __SS__ <<
"GroupID (" << groupID <<
") added to row (" << row
1104 <<
" is already present!" << __E__;
1113 if(getDataView()[row][col] ==
"" ||
1114 getDataView()[row][col] == getDefaultRowValues()[col])
1115 setValue(groupID, row, col);
1117 setValue(groupID +
" | " + getDataView()[row][col], row, col);
1127 bool TableView::removeRowFromGroup(
const unsigned int& row,
1128 const unsigned int& col,
1129 const std::string& groupNeedle,
1130 bool deleteRowIfNoGroupLeft)
1132 __COUT__ <<
"groupNeedle " << groupNeedle << __E__;
1133 std::set<std::string> groupIDList;
1134 if(!isEntryInGroupCol(row, col, groupNeedle, &groupIDList))
1136 __SS__ <<
"GroupID (" << groupNeedle <<
") removed from row (" << row
1137 <<
") was already removed!" << __E__;
1145 std::string newValue =
"";
1146 unsigned int cnt = 0;
1147 for(
const auto& groupID : groupIDList)
1150 if(groupID == groupNeedle)
1155 newValue += groupID;
1158 bool wasDeleted =
false;
1159 if(deleteRowIfNoGroupLeft && newValue ==
"")
1161 __COUT__ <<
"Delete row since it no longer part of any group." << __E__;
1166 setValue(newValue, row, col);
1179 bool TableView::isEntryInGroup(
const unsigned int& r,
1180 const std::string& childLinkIndex,
1181 const std::string& groupNeedle)
const
1183 unsigned int c = getColLinkGroupID(childLinkIndex);
1185 return isEntryInGroupCol(r, c, groupNeedle);
1197 bool TableView::isEntryInGroupCol(
const unsigned int& r,
1198 const unsigned int& c,
1199 const std::string& groupNeedle,
1200 std::set<std::string>* groupIDList)
const
1209 for(; j < theDataView_[r][c].size(); ++j)
1210 if((theDataView_[r][c][j] ==
' ' ||
1211 theDataView_[r][c][j] ==
'|') &&
1214 else if((theDataView_[r][c][j] ==
1216 theDataView_[r][c][j] ==
'|') &&
1220 groupIDList->emplace(theDataView_[r][c].substr(i, j - i));
1224 if(groupNeedle == theDataView_[r][c].substr(i, j - i))
1237 groupIDList->emplace(theDataView_[r][c].substr(i, j - i));
1241 if(groupNeedle == theDataView_[r][c].substr(i, j - i))
1256 std::set<std::string> TableView::getSetOfGroupIDs(
const std::string& childLinkIndex,
1257 unsigned int r)
const
1259 return getSetOfGroupIDs(getColLinkGroupID(childLinkIndex), r);
1261 std::set<std::string> TableView::getSetOfGroupIDs(
const unsigned int& c,
1262 unsigned int r)
const
1266 std::set<std::string> retSet;
1271 if(r != (
unsigned int)-1)
1273 if(r >= getNumberOfRows())
1275 __SS__ <<
"Invalid row requested!" << __E__;
1279 StringMacros::getSetFromString(theDataView_[r][c], retSet);
1307 for(r = 0; r < getNumberOfRows(); ++r)
1309 StringMacros::getSetFromString(theDataView_[r][c], retSet);
1357 const unsigned int TableView::getColLinkGroupID(
const std::string& childLinkIndex)
const
1359 if(!childLinkIndex.size())
1361 __SS__ <<
"Empty childLinkIndex string parameter!" << __E__;
1365 const char* needleChildLinkIndex = &childLinkIndex[0];
1369 size_t spacePos = childLinkIndex.find(
' ');
1370 if(spacePos != std::string::npos &&
1371 spacePos + 1 < childLinkIndex.size())
1374 needleChildLinkIndex = &childLinkIndex[spacePos + 1];
1377 std::map<std::string, unsigned int>::const_iterator it =
1378 colLinkGroupIDs_.find(needleChildLinkIndex);
1380 colLinkGroupIDs_.end())
1384 <<
"Incompatible table for this group link. Table '" << tableName_
1385 <<
"' is missing a GroupID column with data type '"
1386 << TableViewColumnInfo::TYPE_START_GROUP_ID <<
"-" << needleChildLinkIndex
1388 <<
"Note: you can separate the child GroupID column data type from "
1389 <<
"the parent GroupLink column data type; this is accomplished by using a space "
1390 <<
"character at the parent level - the string after the space will be treated "
1392 <<
"child GroupID column data type." << __E__;
1393 ss <<
"Existing Column GroupIDs: " << __E__;
1394 for(
auto& groupIdColPair : colLinkGroupIDs_)
1395 ss <<
"\t" << groupIdColPair.first <<
" : col-" << groupIdColPair.second << __E__;
1397 ss <<
"Existing Column Types: " << __E__;
1398 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1399 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1402 ss << StringMacros::stackTrace() << __E__;
1408 unsigned int TableView::findRow(
unsigned int col,
1409 const std::string& value,
1410 unsigned int offsetRow)
const
1412 for(
unsigned int row = offsetRow; row < theDataView_.size(); ++row)
1414 if(theDataView_[row][col] == value)
1418 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find value=" << value
1419 <<
" in column named " << columnsInfo_[col].getName()
1420 <<
" with type=" << columnsInfo_[col].getType() << __E__;
1428 unsigned int TableView::findRowInGroup(
unsigned int col,
1429 const std::string& value,
1430 const std::string& groupId,
1431 const std::string& childLinkIndex,
1432 unsigned int offsetRow)
const
1434 unsigned int groupIdCol = getColLinkGroupID(childLinkIndex);
1435 for(
unsigned int row = offsetRow; row < theDataView_.size(); ++row)
1437 if(theDataView_[row][col] == value && isEntryInGroupCol(row, groupIdCol, groupId))
1441 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find in group the value=" << value
1442 <<
" in column named '" << columnsInfo_[col].getName()
1443 <<
"' with type=" << columnsInfo_[col].getType() <<
" and GroupID: '"
1444 << groupId <<
"' in column '" << groupIdCol
1445 <<
"' with GroupID child link index '" << childLinkIndex <<
"'" << __E__;
1454 unsigned int TableView::findCol(
const std::string& wildCardName)
const
1456 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1457 if(StringMacros::wildCardMatch(wildCardName ,
1458 columnsInfo_[col].getName() ))
1461 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find column named '" << wildCardName
1463 ss <<
"Existing columns:\n";
1464 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1465 ss <<
"\t" << columnsInfo_[col].getName() <<
"\n";
1467 ss << StringMacros::stackTrace() << __E__;
1477 unsigned int TableView::findColByType(
const std::string& type,
int startingCol)
const
1479 for(
unsigned int col = startingCol; col < columnsInfo_.size(); ++col)
1480 if(columnsInfo_[col].getType() == type)
1488 const std::string& TableView::getUniqueStorageIdentifier(
void)
const
1490 return uniqueStorageIdentifier_;
1494 const std::string& TableView::getTableName(
void)
const {
return tableName_; }
1497 const TableVersion& TableView::getVersion(
void)
const {
return version_; }
1500 const std::string& TableView::getComment(
void)
const {
return comment_; }
1503 const std::string& TableView::getAuthor(
void)
const {
return author_; }
1506 const time_t& TableView::getCreationTime(
void)
const {
return creationTime_; }
1509 const time_t& TableView::getLastAccessTime(
void)
const {
return lastAccessTime_; }
1512 const bool& TableView::getLooseColumnMatching(
void)
const
1514 return fillWithLooseColumnMatching_;
1519 const unsigned int TableView::getDataColumnSize(
void)
const
1522 if(!getNumberOfRows())
1523 return getNumberOfColumns();
1524 return theDataView_[0].size();
1530 const unsigned int& TableView::getSourceColumnMismatch(
void)
const
1532 return sourceColumnMismatchCount_;
1538 const unsigned int& TableView::getSourceColumnMissing(
void)
const
1540 return sourceColumnMissingCount_;
1546 const std::set<std::string>& TableView::getSourceColumnNames(
void)
const
1548 return sourceColumnNames_;
1552 std::set<std::string> TableView::getColumnNames(
void)
const
1554 std::set<std::string> retSet;
1555 for(
auto& colInfo : columnsInfo_)
1556 retSet.emplace(colInfo.getName());
1561 std::map<std::string,
unsigned int > TableView::getColumnNamesMap(
void)
const
1563 std::map<std::string,
unsigned int > retMap;
1565 for(
auto& colInfo : columnsInfo_)
1566 retMap.emplace(std::make_pair(colInfo.getName(), c++));
1571 std::set<std::string> TableView::getColumnStorageNames(
void)
const
1573 std::set<std::string> retSet;
1574 for(
auto& colInfo : columnsInfo_)
1575 retSet.emplace(colInfo.getStorageName());
1580 std::vector<std::string> TableView::getDefaultRowValues(
void)
const
1582 std::vector<std::string> retVec;
1585 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
1592 if(columnsInfo_[col].isChildLink())
1594 const std::vector<std::string>& theDataChoices =
1595 columnsInfo_[col].getDataChoices();
1598 if(!theDataChoices.size() ||
1599 theDataChoices[0] ==
"arbitraryBool=1")
1600 retVec.push_back(columnsInfo_[col].getDefaultValue());
1604 (theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=0");
1609 bool foundDefault =
false;
1611 for(
const auto& choice : theDataChoices)
1612 if(skipOne && !hasSkipped)
1617 else if(choice == columnsInfo_[col].getDefaultValue())
1619 foundDefault =
true;
1624 if(!foundDefault && theDataChoices.size() > (skipOne ? 1 : 0))
1625 retVec.push_back(theDataChoices[(skipOne ? 1 : 0)]);
1627 retVec.push_back(columnsInfo_[col].getDefaultValue());
1631 retVec.push_back(columnsInfo_[col].getDefaultValue());
1638 unsigned int TableView::getNumberOfRows(
void)
const {
return theDataView_.size(); }
1641 unsigned int TableView::getNumberOfColumns(
void)
const {
return columnsInfo_.size(); }
1644 const TableView::DataView& TableView::getDataView(
void)
const {
return theDataView_; }
1653 const std::vector<TableViewColumnInfo>& TableView::getColumnsInfo(
void)
const
1655 return columnsInfo_;
1659 std::vector<TableViewColumnInfo>* TableView::getColumnsInfoP(
void)
1661 return &columnsInfo_;
1666 if(column >= columnsInfo_.size())
1668 std::stringstream errMsg;
1669 errMsg << __COUT_HDR_FL__ <<
"\nCan't find column " << column
1670 <<
"\n\n\n\nThe column info is likely missing due to incomplete "
1671 "Configuration View filling.\n\n"
1673 __THROW__(errMsg.str().c_str());
1675 return columnsInfo_[column];
1680 void TableView::setUniqueStorageIdentifier(
const std::string& storageUID)
1682 uniqueStorageIdentifier_ = storageUID;
1686 void TableView::setTableName(
const std::string& name) { tableName_ = name; }
1689 void TableView::setComment(
const std::string& comment) { comment_ = comment; }
1692 void TableView::setURIEncodedComment(
const std::string& uriComment)
1694 comment_ = StringMacros::decodeURIComponent(uriComment);
1698 void TableView::setAuthor(
const std::string& author) { author_ = author; }
1701 void TableView::setCreationTime(time_t t) { creationTime_ = t; }
1704 void TableView::setLastAccessTime(time_t t) { lastAccessTime_ = t; }
1707 void TableView::setLooseColumnMatching(
bool setValue)
1709 fillWithLooseColumnMatching_ = setValue;
1713 void TableView::reset(
void)
1718 columnsInfo_.clear();
1719 theDataView_.clear();
1723 void TableView::print(std::ostream& out)
const
1725 out <<
"============================================================================="
1728 out <<
"Print: " << tableName_ <<
" Version: " << version_ <<
" Comment: " << comment_
1729 <<
" Author: " << author_ <<
" Creation Time: " << ctime(&creationTime_) << __E__;
1730 out <<
"\t\tNumber of Cols " << getNumberOfColumns() << __E__;
1731 out <<
"\t\tNumber of Rows " << getNumberOfRows() << __E__;
1733 out <<
"Columns:\t";
1734 for(
int i = 0; i < (int)columnsInfo_.size(); ++i)
1735 out << i <<
":" << columnsInfo_[i].getName() <<
":"
1736 << columnsInfo_[i].getStorageName() <<
":" << columnsInfo_[i].getType() <<
":"
1737 << columnsInfo_[i].getDataType() <<
"\t ";
1740 out <<
"Rows:" << __E__;
1743 for(
int r = 0; r < (int)getNumberOfRows(); ++r)
1745 out << (int)r <<
":\t";
1746 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
1748 out << (int)c <<
":";
1751 if(columnsInfo_[c].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
1753 int choiceIndex = -1;
1754 std::vector<std::string> choices = columnsInfo_[c].getDataChoices();
1755 val = StringMacros::convertEnvironmentVariables(theDataView_[r][c]);
1757 if(val == columnsInfo_[c].getDefaultValue())
1761 for(
int i = 0; i < (int)choices.size(); ++i)
1762 if(val == choices[i])
1763 choiceIndex = i + 1;
1766 out <<
"ChoiceIndex=" << choiceIndex <<
":";
1769 out << theDataView_[r][c];
1789 void TableView::printJSON(std::ostream& out)
const
1792 out <<
"\"NAME\" : \"" << tableName_ <<
"\",\n";
1796 out <<
"\"COMMENT\" : ";
1802 for(
unsigned int i = 0; i < val.size(); ++i)
1806 else if(val[i] ==
'\t')
1808 else if(val[i] ==
'\r')
1813 if(val[i] ==
'"' || val[i] ==
'\\')
1820 out <<
"\"AUTHOR\" : \"" << author_ <<
"\",\n";
1821 out <<
"\"CREATION_TIME\" : " << creationTime_ <<
",\n";
1826 out <<
"\"COL_TYPES\" : {\n";
1827 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
1829 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1830 out <<
"\"" << columnsInfo_[c].getDataType() <<
"\"";
1831 if(c + 1 < (
int)getNumberOfColumns())
1837 out <<
"\"DATA_SET\" : [\n";
1839 for(
int r = 0; r < (int)getNumberOfRows(); ++r)
1842 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
1844 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1846 out <<
"\"" << getEscapedValueAsString(r, c,
false)
1849 if(c + 1 < (
int)getNumberOfColumns())
1854 if(r + 1 < (
int)getNumberOfRows())
1866 std::string restoreJSONStringEntities(
const std::string& str)
1868 unsigned int sz = str.size();
1872 std::stringstream retStr;
1874 for(; i < sz - 1; ++i)
1906 retStr << str[sz - 1];
1908 return retStr.str();
1919 int TableView::fillFromJSON(
const std::string& json)
1921 std::vector<std::string> keys;
1922 keys.push_back(
"NAME");
1923 keys.push_back(
"COMMENT");
1924 keys.push_back(
"AUTHOR");
1925 keys.push_back(
"CREATION_TIME");
1927 keys.push_back(
"DATA_SET");
1931 CV_JSON_FILL_COMMENT,
1932 CV_JSON_FILL_AUTHOR,
1933 CV_JSON_FILL_CREATION_TIME,
1935 CV_JSON_FILL_DATA_SET
1940 sourceColumnMismatchCount_ = 0;
1941 sourceColumnMissingCount_ = 0;
1942 sourceColumnNames_.clear();
1943 unsigned int colFoundCount = 0;
1945 unsigned int row = -1;
1946 unsigned int colSpeedup = 0;
1947 unsigned int startString, startNumber, endNumber = -1;
1948 unsigned int bracketCount = 0;
1949 unsigned int sqBracketCount = 0;
1953 bool isDataArray = 0;
1954 bool keyIsMatch, keyIsComment;
1955 unsigned int keyIsMatchIndex, keyIsMatchStorageIndex, keyIsMatchCommentIndex;
1956 const std::string COMMENT_ALT_KEY =
"COMMENT";
1958 std::string extractedString =
"", currKey =
"", currVal =
"";
1959 unsigned int currDepth;
1961 std::vector<std::string> jsonPath;
1962 std::vector<char> jsonPathType;
1963 char lastPopType =
'_';
1965 unsigned int matchedKey = -1;
1966 unsigned int lastCol = -1;
1969 for(; i < json.size(); ++i)
1974 if(i - 1 < json.size() &&
1975 json[i - 1] ==
'\\')
1978 inQuotes = !inQuotes;
1983 extractedString = restoreJSONStringEntities(
1984 json.substr(startString + 1, i - startString - 1));
1993 if(jsonPathType[jsonPathType.size() - 1] !=
'{' ||
1996 __COUT__ <<
"Invalid ':' position" << __E__;
2001 jsonPathType.push_back(
'K');
2002 jsonPath.push_back(extractedString);
2021 if(lastPopType ==
'{')
2024 if(jsonPathType[jsonPathType.size() - 1] ==
'K')
2027 jsonPath.pop_back();
2028 jsonPathType.pop_back();
2034 currVal = extractedString;
2037 if(endNumber == (
unsigned int)-1 ||
2038 endNumber <= startNumber)
2041 if(endNumber <= startNumber)
2044 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
2047 currDepth = bracketCount;
2049 if(jsonPathType[jsonPathType.size() - 1] ==
'K')
2051 currKey = jsonPath[jsonPathType.size() - 1];
2056 jsonPath.pop_back();
2057 jsonPathType.pop_back();
2059 else if(jsonPathType[jsonPathType.size() - 1] ==
2063 for(
unsigned int k = jsonPathType.size() - 2; k < jsonPathType.size();
2065 if(jsonPathType[k] ==
'K')
2067 currKey = jsonPath[k];
2072 __COUT__ <<
"Invalid array position" << __E__;
2081 __COUT__ <<
"Invalid ',' position" << __E__;
2092 jsonPathType.push_back(
'{');
2093 jsonPath.push_back(
"{");
2106 if(lastPopType !=
'{' &&
2107 jsonPathType[jsonPathType.size() - 1] ==
'K')
2109 currDepth = bracketCount;
2110 currKey = jsonPath[jsonPathType.size() - 1];
2112 currVal = extractedString;
2115 if(endNumber == (
unsigned int)-1 ||
2116 endNumber <= startNumber)
2119 if(endNumber <= startNumber)
2123 json.substr(startNumber + 1, endNumber - startNumber - 1);
2127 jsonPath.pop_back();
2128 jsonPathType.pop_back();
2131 if(jsonPathType[jsonPathType.size() - 1] !=
'{')
2133 __COUT__ <<
"Invalid '}' position" << __E__;
2137 jsonPath.pop_back();
2138 jsonPathType.pop_back();
2144 jsonPathType.push_back(
'[');
2145 jsonPath.push_back(
"[");
2154 if(jsonPathType[jsonPathType.size() - 1] !=
'[')
2156 __COUT__ <<
"Invalid ']' position" << __E__;
2160 currDepth = bracketCount;
2164 currVal = extractedString;
2167 if(endNumber == (
unsigned int)-1 ||
2168 endNumber <= startNumber)
2171 if(endNumber <= startNumber)
2174 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
2179 for(
unsigned int k = jsonPathType.size() - 2; k < jsonPathType.size(); --k)
2180 if(jsonPathType[k] ==
'K')
2182 currKey = jsonPath[k];
2187 __COUT__ <<
"Invalid array position" << __E__;
2192 if(jsonPathType[jsonPathType.size() - 1] !=
'[')
2194 __COUT__ <<
"Invalid ']' position" << __E__;
2198 jsonPath.pop_back();
2199 jsonPathType.pop_back();
2208 if(startNumber != (
unsigned int)-1 && endNumber == (
unsigned int)-1)
2220 if(0 && tableName_ ==
"ARTDAQ_DATALOGGER_TABLE")
2222 std::cout << i <<
":\t" << json[i] <<
" - ";
2232 std::cout <<
"ExtKey=";
2233 for(
unsigned int k = 0; k < jsonPath.size(); ++k)
2234 std::cout << jsonPath[k] <<
"/";
2236 std::cout << lastPopType <<
" ";
2237 std::cout << bracketCount <<
" ";
2238 std::cout << sqBracketCount <<
" ";
2239 std::cout << inQuotes <<
" ";
2240 std::cout << newValue <<
"-";
2241 std::cout << currKey <<
"-{" << currDepth <<
"}:";
2242 std::cout << currVal <<
" ";
2243 std::cout << startNumber <<
"-";
2244 std::cout << endNumber <<
" ";
2246 __COUTV__(fillWithLooseColumnMatching_);
2255 for(
unsigned int k = 0; k < keys.size(); ++k)
2256 if((currDepth == 1 && keys[k] == currKey) ||
2257 (currDepth > 1 && keys[k] == jsonPath[1]))
2260 if(matchedKey != (
unsigned int)-1)
2267 case CV_JSON_FILL_NAME:
2269 setTableName(currVal);
2271 case CV_JSON_FILL_COMMENT:
2273 setComment(currVal);
2275 case CV_JSON_FILL_AUTHOR:
2279 case CV_JSON_FILL_CREATION_TIME:
2281 setCreationTime(strtol(currVal.c_str(), 0, 10));
2286 case CV_JSON_FILL_DATA_SET:
2298 unsigned int col, ccnt = 0;
2299 unsigned int noc = getNumberOfColumns();
2300 for(; ccnt < noc; ++ccnt)
2306 if(fillWithLooseColumnMatching_)
2319 if(getNumberOfRows() == 1)
2320 sourceColumnNames_.emplace(currKey);
2324 if(row >= getNumberOfRows())
2326 __SS__ <<
"Invalid row"
2328 std::cout << ss.str();
2333 theDataView_[row][col] =
2341 col = (ccnt + colSpeedup) % noc;
2347 keyIsComment =
true;
2348 for(keyIsMatchIndex = 0,
2349 keyIsMatchStorageIndex = 0,
2350 keyIsMatchCommentIndex = 0;
2351 keyIsMatchIndex < currKey.size();
2354 if(columnsInfo_[col]
2355 .getStorageName()[keyIsMatchStorageIndex] ==
2357 ++keyIsMatchStorageIndex;
2359 if(currKey[keyIsMatchIndex] ==
'_')
2363 if(keyIsMatchStorageIndex >=
2364 columnsInfo_[col].getStorageName().size() ||
2365 currKey[keyIsMatchIndex] !=
2367 .getStorageName()[keyIsMatchStorageIndex])
2377 keyIsMatchCommentIndex < COMMENT_ALT_KEY.size())
2379 if(currKey[keyIsMatchIndex] !=
2380 COMMENT_ALT_KEY[keyIsMatchCommentIndex])
2383 keyIsComment =
false;
2387 ++keyIsMatchStorageIndex;
2398 if(getNumberOfRows())
2399 sourceColumnMissingCount_ +=
2400 getNumberOfColumns() - colFoundCount;
2408 if(getNumberOfRows() == 1)
2409 sourceColumnNames_.emplace(currKey);
2413 if(row >= getNumberOfRows())
2415 __SS__ <<
"Invalid row"
2417 __COUT__ <<
"\n" << ss.str();
2422 theDataView_[row][col] = currVal;
2428 if(ccnt >= getNumberOfColumns())
2431 <<
"Invalid column in JSON source data: " << currKey
2432 <<
" not found in column names of table named "
2433 << getTableName() <<
"."
2438 ++sourceColumnMismatchCount_;
2439 if(getNumberOfRows() ==
2441 sourceColumnNames_.emplace(currKey);
2444 __COUT_WARN__ <<
"Trying to ignore error, and not populating "
2449 colSpeedup = (colSpeedup + 1) % noc;
2471 if(!fillWithLooseColumnMatching_ && sourceColumnMissingCount_ > 0)
2473 __SS__ <<
"Can not ignore errors because not every column was found in the "
2475 <<
". Please see the details below:\n\n"
2476 <<
"The source column size was found to be " << getDataColumnSize()
2477 <<
", and the current number of columns for this table is "
2478 << getNumberOfColumns() <<
". This resulted in a count of "
2479 << getSourceColumnMismatch()
2480 <<
" source column mismatches, and a count of " << getSourceColumnMissing()
2481 <<
" table entries missing in " << getNumberOfRows() <<
" row(s) of data."
2484 const std::set<std::string> srcColNames = getSourceColumnNames();
2485 ss <<
"\n\nSource column names in ALPHABETICAL order were as follows:\n";
2487 std::string preIndexStr =
"";
2488 for(
auto& srcColName : srcColNames)
2490 ss <<
"\n\t" << preIndexStr << index <<
". " << srcColName;
2501 std::set<std::string> destColNames = getColumnStorageNames();
2502 ss <<
"\n\nCurrent table column names in ALPHABETICAL order are as follows:\n";
2505 for(
auto& destColName : destColNames)
2507 ss <<
"\n\t" << preIndexStr << index <<
". " << destColName;
2517 ss << StringMacros::stackTrace();
2527 bool TableView::isURIEncodedCommentTheSame(
const std::string& comment)
const
2529 std::string compareStr = StringMacros::decodeURIComponent(comment);
2530 return comment_ == compareStr;
2589 int TableView::fillFromCSV(
const std::string& data,
2590 const int& dataOffset,
2591 const std::string& author)
2599 int j = data.find(
',', i);
2600 int k = data.find(
';', i);
2602 bool rowWasModified;
2603 unsigned int countRowsModified = 0;
2604 int authorCol = findColByType(TableViewColumnInfo::TYPE_AUTHOR);
2605 int timestampCol = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
2608 while(k != (
int)(std::string::npos))
2610 rowWasModified =
false;
2611 if(r >= (
int)getNumberOfRows())
2615 rowWasModified =
true;
2618 while(j < k && j != (
int)(std::string::npos))
2623 if(c >= (
int)getNumberOfColumns() - 2)
2626 j = data.find(
',', i);
2631 if(setURIEncodedValue(data.substr(i, j - i), r, c))
2632 rowWasModified =
true;
2635 j = data.find(
',', i);
2640 if(author !=
"" && rowWasModified)
2642 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << __E__;
2643 setValue(author, r, authorCol);
2644 setValue(time(0), r, timestampCol);
2648 ++countRowsModified;
2654 j = data.find(
',', i);
2655 k = data.find(
';', i);
2659 while(r < (
int)getNumberOfRows())
2662 __COUT__ <<
"Row deleted: " << (int)r << __E__;
2663 ++countRowsModified;
2666 __COUT_INFO__ <<
"countRowsModified=" << countRowsModified << __E__;
2668 if(!countRowsModified)
2673 bool match = getColumnStorageNames().size() == getSourceColumnNames().size();
2676 for(
auto& destColName : getColumnStorageNames())
2677 if(getSourceColumnNames().find(destColName) ==
2678 getSourceColumnNames().end())
2680 __COUT__ <<
"Found column name mismach for '" << destColName
2681 <<
"'... So allowing same data!" << __E__;
2690 __SS__ <<
"No rows were modified! No reason to fill a view with same content."
2692 __COUT__ <<
"\n" << ss.str();
2702 sourceColumnNames_.clear();
2703 for(
unsigned int i = 0; i < getNumberOfColumns(); ++i)
2704 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
2725 bool TableView::setURIEncodedValue(
const std::string& value,
2726 const unsigned int& r,
2727 const unsigned int& c,
2728 const std::string& author)
2730 if(!(c < columnsInfo_.size() && r < getNumberOfRows()))
2732 __SS__ <<
"Invalid row (" << (int)r <<
") col (" << (
int)c << ") requested!"
2733 << "Number of Rows = " << getNumberOfRows()
2734 << "Number of Columns = " << columnsInfo_.size() << __E__;
2739 std::
string valueStr =
StringMacros::decodeURIComponent(value);
2740 std::
string originalValueStr =
2741 getValueAsString(r, c, false);
2749 std::string convertedString = StringMacros::convertEnvironmentVariables(valueStr);
2764 theDataView_[r][c] = valueStr;
2766 else if(columnsInfo_[c].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
2778 setValue(time_t(strtol(valueStr.c_str(), 0, 10)), r, c);
2781 theDataView_[r][c] = valueStr;
2783 bool rowWasModified =
2784 (originalValueStr !=
2785 getValueAsString(r, c,
false));
2788 if(author !=
"" && rowWasModified)
2790 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << __E__;
2791 int authorCol = findColByType(TableViewColumnInfo::TYPE_AUTHOR);
2792 int timestampCol = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
2793 setValue(author, r, authorCol);
2794 setValue(time(0), r, timestampCol);
2797 return rowWasModified;
2801 void TableView::resizeDataView(
unsigned int nRows,
unsigned int nCols)
2805 theDataView_.resize(nRows, std::vector<std::string>(nCols));
2815 unsigned int TableView::addRow(
const std::string& author,
2816 unsigned char incrementUniqueData,
2817 std::string baseNameAutoUID,
2818 unsigned int rowToAdd)
2821 if(rowToAdd == (
unsigned int)-1)
2822 rowToAdd = getNumberOfRows();
2824 theDataView_.resize(getNumberOfRows() + 1,
2825 std::vector<std::string>(getNumberOfColumns()));
2828 for(
unsigned int r = getNumberOfRows() - 2; r >= rowToAdd; --r)
2830 if(r == (
unsigned int)-1)
2832 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
2833 theDataView_[r + 1][col] = theDataView_[r][col];
2836 std::vector<std::string> defaultRowValues = getDefaultRowValues();
2838 char indexString[1000];
2839 std::string tmpString, baseString;
2842 unsigned int maxUniqueData;
2843 std::string numString;
2848 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
2855 if(incrementUniqueData &&
2856 (col == getColUID() ||
2857 (getNumberOfRows() > 1 &&
2858 (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_DATA ||
2859 columnsInfo_[col].getType() ==
2860 TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA))))
2876 for(
unsigned int r = 0; r < getNumberOfRows(); ++r)
2884 tmpString = theDataView_[r][col];
2888 for(index = tmpString.length() - 1; index < tmpString.length(); --index)
2892 if(!(tmpString[index] >=
'0' && tmpString[index] <=
'9'))
2899 if(tmpString.length() && foundAny)
2902 numString = tmpString.substr(index + 1);
2903 tmpString = tmpString.substr(0, index + 1);
2910 sscanf(numString.c_str(),
"%u", &index);
2912 if(index > maxUniqueData)
2914 maxUniqueData = index;
2915 baseString = tmpString;
2922 sprintf(indexString,
"%u", maxUniqueData);
2926 if(col == getColUID())
2929 if(baseNameAutoUID !=
"")
2930 theDataView_[rowToAdd][col] = baseNameAutoUID + indexString;
2932 theDataView_[rowToAdd][col] = baseString + indexString;
2935 theDataView_[rowToAdd][col] = baseString + indexString;
2937 __COUT__ <<
"New unique data entry is data[" << rowToAdd <<
"][" << col
2938 <<
"] = '" << theDataView_[rowToAdd][col] <<
"'" << __E__;
2943 theDataView_[rowToAdd][col] = defaultRowValues[col];
2948 __COUT__ <<
"Row=" << rowToAdd <<
" was created!" << __E__;
2949 int authorCol = findColByType(TableViewColumnInfo::TYPE_AUTHOR);
2950 int timestampCol = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
2951 setValue(author, rowToAdd, authorCol);
2952 setValue(time(0), rowToAdd, timestampCol);
2961 void TableView::deleteRow(
int r)
2963 if(r >= (
int)getNumberOfRows())
2966 __SS__ <<
"Row " << (int)r
2967 <<
" is out of bounds (Row Count = " << getNumberOfRows()
2968 <<
") and can not be deleted." << __E__;
2972 theDataView_.erase(theDataView_.begin() + r);
2991 const bool TableView::getChildLink(
2992 const unsigned int& c,
2994 std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>& linkPair)
const
2996 if(!(c < columnsInfo_.size()))
2998 __SS__ <<
"Invalid col (" << (int)c <<
") requested for child link!" << __E__;
3006 if((isGroup = columnsInfo_[c].isChildLinkGroupID()) ||
3007 columnsInfo_[c].isChildLinkUID())
3011 linkPair.second = c;
3012 std::string index = columnsInfo_[c].getChildLinkIndex();
3017 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
3023 else if(columnsInfo_[col].isChildLink() &&
3024 index == columnsInfo_[col].getChildLinkIndex())
3029 linkPair.first = col;
3035 __SS__ <<
"\tIn view: " << tableName_
3036 <<
", Can't find complete child link for column name "
3037 << columnsInfo_[c].getName() << __E__;
3041 if(!columnsInfo_[c].isChildLink())
3046 std::string index = columnsInfo_[c].getChildLinkIndex();
3051 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
3068 if(((columnsInfo_[col].isChildLinkUID() && !(isGroup =
false)) ||
3069 (columnsInfo_[col].isChildLinkGroupID() && (isGroup =
true))) &&
3070 index == columnsInfo_[col].getChildLinkIndex())
3075 linkPair.second = col;
3081 __SS__ <<
"\tIn view: " << tableName_
3082 <<
", Can't find complete child link id for column name "
3083 << columnsInfo_[c].getName() << __E__;