1 #include "otsdaq-core/TableCore/TableView.h"
11 #define __MF_SUBJECT__ "TableView-" + tableName_
13 #define __COUT_HDR__ "v" << version_ << ":" << __COUT_HDR_FL__
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_;
70 unsigned int TableView::copyRows(
const std::string& author,
72 unsigned int srcOffsetRow,
73 unsigned int srcRowsToCopy,
74 unsigned int destOffsetRow,
75 bool generateUniqueDataColumns)
81 unsigned int retRow = (
unsigned int)-1;
84 if(src.getNumberOfColumns() != getNumberOfColumns())
86 __SS__ <<
"Error! Number of Columns of source view must match destination view."
87 <<
"Dimension of source is [" << src.getNumberOfColumns()
88 <<
"] and of destination is [" << getNumberOfColumns() <<
"]." << __E__;
92 unsigned int srcRows = src.getNumberOfRows();
94 for(
unsigned int r = 0; r < srcRowsToCopy; ++r)
96 if(r + srcOffsetRow >= srcRows)
99 destOffsetRow = addRow(author,
100 generateUniqueDataColumns ,
104 if(retRow == (
unsigned int)-1)
105 retRow = destOffsetRow;
108 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
109 if(generateUniqueDataColumns &&
110 (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_DATA ||
111 columnsInfo_[col].getType() ==
112 TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA))
115 theDataView_[destOffsetRow][col] =
116 src.theDataView_[r + srcOffsetRow][col];
132 void TableView::init(
void)
138 std::set<std::string> colNameSet;
139 std::string capsColName, colName;
140 for(
auto& colInfo : columnsInfo_)
142 colName = colInfo.getStorageName();
143 if(colName ==
"COMMENT_DESCRIPTION")
146 for(
unsigned int i = 0; i < colName.size(); ++i)
148 if(colName[i] ==
'_')
150 capsColName += colName[i];
153 colNameSet.emplace(capsColName);
156 if(colNameSet.size() != columnsInfo_.size())
158 __SS__ <<
"Table Error:\t"
159 <<
" Columns names must be unique! There are " << columnsInfo_.size()
160 <<
" columns and the unique name count is " << colNameSet.size()
168 getOrInitColStatus();
175 getOrInitColPriority();
183 if((colPos = findColByType(TableViewColumnInfo::TYPE_COMMENT)) != INVALID)
185 if(columnsInfo_[colPos].getName() != TableViewColumnInfo::COL_NAME_COMMENT)
187 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
188 <<
" data type column must have name="
189 << TableViewColumnInfo::COL_NAME_COMMENT << __E__;
193 if(findColByType(TableViewColumnInfo::TYPE_COMMENT, colPos + 1) !=
196 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
197 <<
" data type in column " << columnsInfo_[colPos].getName()
198 <<
" is repeated. This is not allowed." << __E__;
202 if(colPos != getNumberOfColumns() - 3)
204 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
205 <<
" data type column must be 3rd to last (in column "
206 << getNumberOfColumns() - 3 <<
")." << __E__;
212 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
213 <<
" data type column "
214 <<
" is missing. This is not allowed." << __E__;
219 if((colPos = findColByType(TableViewColumnInfo::TYPE_AUTHOR)) != INVALID)
221 if(findColByType(TableViewColumnInfo::TYPE_AUTHOR, colPos + 1) !=
224 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR
225 <<
" data type in column " << columnsInfo_[colPos].getName()
226 <<
" is repeated. This is not allowed." << __E__;
230 if(colPos != getNumberOfColumns() - 2)
232 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR
233 <<
" data type column must be 2nd to last (in column "
234 << getNumberOfColumns() - 2 <<
")." << __E__;
240 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_AUTHOR
241 <<
" data type column "
242 <<
" is missing. This is not allowed." << __E__;
247 if((colPos = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP)) != INVALID)
249 if(findColByType(TableViewColumnInfo::TYPE_TIMESTAMP, colPos + 1) !=
252 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP
253 <<
" data type in column " << columnsInfo_[colPos].getName()
254 <<
" is repeated. This is not allowed." << __E__;
258 if(colPos != getNumberOfColumns() - 1)
260 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP
261 <<
" data type column must be last (in column "
262 << getNumberOfColumns() - 1 <<
")." << __E__;
263 __COUT_ERR__ <<
"\n" << ss.str();
269 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_TIMESTAMP
270 <<
" data type column "
271 <<
" is missing. This is not allowed." << __E__;
278 std::set<std::string > uidSet;
279 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
281 if(uidSet.find(theDataView_[row][colUID_]) != uidSet.end())
283 __SS__ << (
"Entries in UID are not unique. Specifically at row=" +
284 std::to_string(row) +
" value=" + theDataView_[row][colUID_])
289 if(theDataView_[row][colUID_].size() == 0)
291 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' "
292 <<
" was identified. UIDs must contain at least 1 character."
297 for(
unsigned int i = 0; i < theDataView_[row][colUID_].size(); ++i)
298 if(!((theDataView_[row][colUID_][i] >=
'A' &&
299 theDataView_[row][colUID_][i] <=
'Z') ||
300 (theDataView_[row][colUID_][i] >=
'a' &&
301 theDataView_[row][colUID_][i] <=
'z') ||
302 (theDataView_[row][colUID_][i] >=
'0' &&
303 theDataView_[row][colUID_][i] <=
'9') ||
304 (theDataView_[row][colUID_][i] ==
'-' ||
305 theDataView_[row][colUID_][i] <=
'_')))
307 __SS__ <<
"An invalid UID '" << theDataView_[row][colUID_] <<
"' "
308 <<
" was identified. UIDs must contain only letters, numbers,"
309 <<
"dashes, and underscores." << __E__;
313 uidSet.insert(theDataView_[row][colUID_]);
315 if(uidSet.size() != getNumberOfRows())
317 __SS__ <<
"Entries in UID are not unique!"
318 <<
"There are " << getNumberOfRows()
319 <<
" records and the unique UID count is " << uidSet.size() << __E__;
324 colPos = (
unsigned int)-1;
325 while((colPos = findColByType(TableViewColumnInfo::TYPE_UNIQUE_DATA,
326 colPos + 1)) != INVALID)
328 std::set<std::string > uDataSet;
329 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
331 if(uDataSet.find(theDataView_[row][colPos]) != uDataSet.end())
333 __SS__ <<
"Entries in Unique Data column "
334 << columnsInfo_[colPos].getName()
335 << (
" are not unique. Specifically at row=" +
336 std::to_string(row) +
337 " value=" + theDataView_[row][colPos])
341 uDataSet.insert(theDataView_[row][colPos]);
343 if(uDataSet.size() != getNumberOfRows())
345 __SS__ <<
"Entries in Unique Data column "
346 << columnsInfo_[colPos].getName() <<
" are not unique!"
347 <<
"There are " << getNumberOfRows()
348 <<
" records and the unique data count is " << uDataSet.size()
356 colPos = (
unsigned int)-1;
357 while((colPos = findColByType(TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA,
358 colPos + 1)) != INVALID)
363 for(
unsigned int groupIdColPos = 0; groupIdColPos < columnsInfo_.size();
365 if(columnsInfo_[groupIdColPos].isGroupID())
367 std::map<std::string ,
368 std::pair<
unsigned int ,
369 std::set<std::string > > >
372 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
374 auto groupIds = getSetOfGroupIDs(groupIdColPos, row);
376 for(
const auto& groupId : groupIds)
378 uGroupDataSets[groupId].first++;
380 if(uGroupDataSets[groupId].second.find(
381 theDataView_[row][colPos]) !=
382 uGroupDataSets[groupId].second.end())
384 __SS__ <<
"Entries in Unique Group Data column " << colPos
385 <<
":" << columnsInfo_[colPos].getName()
386 <<
" are not unique for group ID '" << groupId
387 <<
".' Specifically at row=" << std::to_string(row)
388 <<
" value=" << theDataView_[row][colPos] << __E__;
391 uGroupDataSets[groupId].second.insert(
392 theDataView_[row][colPos]);
396 for(
const auto& groupPair : uGroupDataSets)
397 if(uGroupDataSets[groupPair.first].second.size() !=
398 uGroupDataSets[groupPair.first].first)
401 <<
"Entries in Unique Data column "
402 << columnsInfo_[colPos].getName()
403 <<
" are not unique for group '" << groupPair.first
405 <<
"There are " << uGroupDataSets[groupPair.first].first
406 <<
" records and the unique data count is "
407 << uGroupDataSets[groupPair.first].second.size() << __E__;
413 auto rowDefaults = getDefaultRowValues();
420 std::set<std::string> groupIdIndexes, childLinkIndexes, childLinkIdLabels;
421 unsigned int groupIdIndexesCount = 0, childLinkIndexesCount = 0,
422 childLinkIdLabelsCount = 0;
424 std::pair<
unsigned int ,
unsigned int > tmpLinkPair;
426 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
428 if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
430 const std::vector<std::string>& theDataChoices =
431 columnsInfo_[col].getDataChoices();
434 if(theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=1")
438 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
442 if(theDataView_[row][col] == rowDefaults[col])
445 for(
const auto& choice : theDataChoices)
447 if(theDataView_[row][col] == choice)
455 __SS__ << getTableName() <<
" Error:\t'" << theDataView_[row][col]
456 <<
"' in column " << columnsInfo_[col].getName()
457 <<
" is not a valid Fixed Choice option. "
458 <<
"Possible values are as follows: ";
460 for(
unsigned int i = 0;
461 i < columnsInfo_[col].getDataChoices().size();
466 ss << columnsInfo_[col].getDataChoices()[i];
473 else if(columnsInfo_[col].isChildLink())
477 const std::vector<std::string>& theDataChoices =
478 columnsInfo_[col].getDataChoices();
481 if(!theDataChoices.size() || theDataChoices[0] ==
"arbitraryBool=1")
486 (theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=0");
490 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
495 for(
const auto& choice : theDataChoices)
497 if(skipOne && !hasSkipped)
503 if(theDataView_[row][col] == choice)
511 __SS__ << getTableName() <<
" Error:\t the value '"
512 << theDataView_[row][col] <<
"' in column "
513 << columnsInfo_[col].getName()
514 <<
" is not a valid Fixed Choice option. "
515 <<
"Possible values are as follows: ";
520 for(
unsigned int i = skipOne ? 1 : 0;
521 i < columnsInfo_[col].getDataChoices().size();
524 if(i > (skipOne ? 1 : 0))
526 ss << columnsInfo_[col].getDataChoices()[i];
533 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_ON_OFF)
534 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
536 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" ||
537 theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
538 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_ON;
539 else if(theDataView_[row][col] ==
"0" ||
540 theDataView_[row][col] ==
"off" ||
541 theDataView_[row][col] ==
"Off" ||
542 theDataView_[row][col] ==
"OFF")
543 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_OFF;
546 __SS__ << getTableName() <<
" Error:\t the value '"
547 << theDataView_[row][col] <<
"' in column "
548 << columnsInfo_[col].getName()
549 <<
" is not a valid Type (On/Off) std::string. Possible "
550 "values are 1, on, On, ON, 0, off, Off, OFF."
555 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_TRUE_FALSE)
556 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
558 if(theDataView_[row][col] ==
"1" ||
559 theDataView_[row][col] ==
"true" ||
560 theDataView_[row][col] ==
"True" ||
561 theDataView_[row][col] ==
"TRUE")
562 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_TRUE;
563 else if(theDataView_[row][col] ==
"0" ||
564 theDataView_[row][col] ==
"false" ||
565 theDataView_[row][col] ==
"False" ||
566 theDataView_[row][col] ==
"FALSE")
567 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_FALSE;
570 __SS__ << getTableName() <<
" Error:\t the value '"
571 << theDataView_[row][col] <<
"' in column "
572 << columnsInfo_[col].getName()
573 <<
" is not a valid Type (True/False) std::string. "
574 "Possible values are 1, true, True, TRUE, 0, false, "
580 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_YES_NO)
581 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
583 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" ||
584 theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
585 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_YES;
586 else if(theDataView_[row][col] ==
"0" ||
587 theDataView_[row][col] ==
"no" ||
588 theDataView_[row][col] ==
"No" ||
589 theDataView_[row][col] ==
"NO")
590 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_NO;
593 __SS__ << getTableName() <<
" Error:\t the value '"
594 << theDataView_[row][col] <<
"' in column "
595 << columnsInfo_[col].getName()
596 <<
" is not a valid Type (Yes/No) std::string. Possible "
597 "values are 1, yes, Yes, YES, 0, no, No, NO."
602 else if(columnsInfo_[col].isGroupID())
604 colLinkGroupIDs_[columnsInfo_[col].getChildLinkIndex()] =
607 groupIdIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
608 ++groupIdIndexesCount;
610 else if(columnsInfo_[col].isChildLink())
613 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
614 if(theDataView_[row][col] ==
"NoLink" ||
615 theDataView_[row][col] ==
"No_Link" ||
616 theDataView_[row][col] ==
"NOLINK" ||
617 theDataView_[row][col] ==
"NO_LINK" ||
618 theDataView_[row][col] ==
"Nolink" ||
619 theDataView_[row][col] ==
"nolink" ||
620 theDataView_[row][col] ==
"noLink")
621 theDataView_[row][col] =
622 TableViewColumnInfo::DATATYPE_LINK_DEFAULT;
625 childLinkIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
626 ++childLinkIndexesCount;
629 if(columnsInfo_[col].getDataType() !=
630 TableViewColumnInfo::DATATYPE_STRING)
632 __SS__ << getTableName() <<
" Error:\t"
633 <<
"Column " << col <<
" with name '"
634 << columnsInfo_[col].getName()
635 <<
"' is a Child Link column and has an illegal data type of '"
636 << columnsInfo_[col].getDataType()
637 <<
"'. The data type for Child Link columns must be "
638 << TableViewColumnInfo::DATATYPE_STRING << __E__;
643 getChildLink(col, tmpIsGroup, tmpLinkPair);
645 else if(columnsInfo_[col].isChildLinkUID() ||
646 columnsInfo_[col].isChildLinkGroupID())
649 childLinkIdLabels.emplace(columnsInfo_[col].getChildLinkIndex());
650 ++childLinkIdLabelsCount;
653 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
654 if(theDataView_[row][col] ==
"")
655 theDataView_[row][col] = rowDefaults[col];
658 getChildLink(col, tmpIsGroup, tmpLinkPair);
663 if(groupIdIndexes.size() != groupIdIndexesCount)
665 __SS__ << (
"GroupId Labels are not unique!") <<
"There are "
666 << groupIdIndexesCount <<
" GroupId Labels and the unique count is "
667 << groupIdIndexes.size() << __E__;
670 if(childLinkIndexes.size() != childLinkIndexesCount)
672 __SS__ << (
"Child Link Labels are not unique!") <<
"There are "
673 << childLinkIndexesCount
674 <<
" Child Link Labels and the unique count is "
675 << childLinkIndexes.size() << __E__;
678 if(childLinkIdLabels.size() != childLinkIdLabelsCount)
680 __SS__ << (
"Child Link ID Labels are not unique!") <<
"There are "
681 << childLinkIdLabelsCount
682 <<
" Child Link ID Labels and the unique count is "
683 << childLinkIdLabels.size() << __E__;
689 __COUT__ <<
"Error occured in TableView::init() for version=" << version_
700 void TableView::getValue(std::string& value,
703 bool doConvertEnvironmentVariables)
const
705 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
707 __SS__ <<
"Invalid row col requested" << __E__;
711 value = validateValueForColumn(
712 theDataView_[row][col], col, doConvertEnvironmentVariables);
720 std::string TableView::validateValueForColumn(
const std::string& value,
722 bool doConvertEnvironmentVariables)
const
724 if(col >= columnsInfo_.size())
726 __SS__ <<
"Invalid col requested" << __E__;
730 if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_STRING)
731 return doConvertEnvironmentVariables
732 ? StringMacros::convertEnvironmentVariables(value)
734 else if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
736 return StringMacros::getTimestampString(
737 doConvertEnvironmentVariables
738 ? StringMacros::convertEnvironmentVariables(value)
752 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
753 <<
" in configuration " << tableName_
754 <<
" at column=" << columnsInfo_[col].getName()
755 <<
" for getValue with type '"
756 << StringMacros::demangleTypeName(
typeid(std::string).name()) <<
"'"
768 std::string TableView::getValueAsString(
unsigned int row,
770 bool doConvertEnvironmentVariables)
const
772 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
774 __SS__ << (
"Invalid row col requested") << __E__;
780 if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_ON_OFF)
782 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" ||
783 theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
784 return TableViewColumnInfo::TYPE_VALUE_ON;
786 return TableViewColumnInfo::TYPE_VALUE_OFF;
788 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_TRUE_FALSE)
790 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" ||
791 theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
792 return TableViewColumnInfo::TYPE_VALUE_TRUE;
794 return TableViewColumnInfo::TYPE_VALUE_FALSE;
796 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_YES_NO)
798 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" ||
799 theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
800 return TableViewColumnInfo::TYPE_VALUE_YES;
802 return TableViewColumnInfo::TYPE_VALUE_NO;
806 return doConvertEnvironmentVariables
807 ? StringMacros::convertEnvironmentVariables(theDataView_[row][col])
808 : theDataView_[row][col];
817 std::string TableView::getEscapedValueAsString(
unsigned int row,
819 bool doConvertEnvironmentVariables)
const
821 std::string val = getValueAsString(row, col, doConvertEnvironmentVariables);
822 std::string retVal =
"";
823 retVal.reserve(val.size());
824 for(
unsigned int i = 0; i < val.size(); ++i)
828 else if(val[i] ==
'\t')
830 else if(val[i] ==
'\r')
835 if(val[i] ==
'"' || val[i] ==
'\\')
846 void TableView::setValue(
const std::string& value,
unsigned int row,
unsigned int col)
848 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
850 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
854 if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_STRING)
855 theDataView_[row][col] = value;
859 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
860 <<
" in configuration " << tableName_
861 <<
" at column=" << columnsInfo_[col].getName()
862 <<
" for setValue with type '"
863 << StringMacros::demangleTypeName(
typeid(value).name()) <<
"'" << __E__;
867 void TableView::setValue(
const char* value,
unsigned int row,
unsigned int col)
869 setValue(std::string(value), row, col);
875 void TableView::setValueAsString(
const std::string& value,
879 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
881 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
885 theDataView_[row][col] = value;
891 const unsigned int TableView::getOrInitColUID(
void)
893 if(colUID_ != INVALID)
897 colUID_ = findColByType(TableViewColumnInfo::TYPE_UID);
898 if(colUID_ == INVALID)
900 __COUT__ <<
"Column Types: " << __E__;
901 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
902 std::cout << columnsInfo_[col].getType() <<
"() "
903 << columnsInfo_[col].getName() << __E__;
904 __SS__ <<
"\tMissing UID Column in table named '" << tableName_ <<
"'" << __E__;
913 const unsigned int TableView::getColUID(
void)
const
915 if(colUID_ != INVALID)
918 __COUT__ <<
"Column Types: " << __E__;
919 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
920 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
923 __SS__ << (
"Missing UID Column in config named " + tableName_ +
924 ". (Possibly TableView was just not initialized?" +
925 "This is the const call so can not alter class members)")
933 const unsigned int TableView::getOrInitColStatus(
void)
935 if(colStatus_ != INVALID)
939 colStatus_ = findCol(TableViewColumnInfo::COL_NAME_STATUS);
940 if(colStatus_ == INVALID)
942 __SS__ <<
"\tMissing " << TableViewColumnInfo::COL_NAME_STATUS
943 <<
" Column in table named '" << tableName_ <<
"'" << __E__;
944 ss <<
"Column Types: " << __E__;
945 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
946 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
957 const unsigned int TableView::getOrInitColPriority(
void)
959 if(colPriority_ != INVALID)
964 findCol(
"*" + TableViewColumnInfo::COL_NAME_PRIORITY);
965 if(colPriority_ == INVALID)
967 __SS__ <<
"\tMissing " << TableViewColumnInfo::COL_NAME_PRIORITY
968 <<
" Column in table named '" << tableName_ <<
"'" << __E__;
969 ss <<
"Column Types: " << __E__;
970 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
971 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
983 const unsigned int TableView::getColStatus(
void)
const
985 if(colStatus_ != INVALID)
988 __COUT__ <<
"\n\nTable '" << tableName_ <<
"' Columns: " << __E__;
989 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
990 std::cout <<
"\t" << columnsInfo_[col].getType() <<
"() "
991 << columnsInfo_[col].getName() << __E__;
995 __SS__ <<
"Missing " << TableViewColumnInfo::COL_NAME_STATUS
996 <<
" Column in config named " << tableName_
997 <<
". (Possibly TableView was just not initialized?"
998 <<
"This is the const call so can not alter class members)" << __E__;
1006 const unsigned int TableView::getColPriority(
void)
const
1008 if(colPriority_ != INVALID)
1009 return colPriority_;
1011 __COUT__ <<
"Priority column was not found... \nColumn Types: " << __E__;
1012 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1013 std::cout <<
"\t" << columnsInfo_[col].getType() <<
"() "
1014 << columnsInfo_[col].getName() << __E__;
1017 __SS__ <<
"Missing " << TableViewColumnInfo::COL_NAME_PRIORITY
1018 <<
" Column in config named " << tableName_
1019 <<
". (The Priority column is identified when TableView is initialized)"
1028 void TableView::addRowToGroup(
1029 const unsigned int& row,
1030 const unsigned int& col,
1031 const std::string& groupID)
1034 if(isEntryInGroupCol(row, col, groupID))
1036 __SS__ <<
"GroupID (" << groupID <<
") added to row (" << row
1037 <<
" is already present!" << __E__;
1046 if(getDataView()[row][col] ==
"" ||
1047 getDataView()[row][col] == getDefaultRowValues()[col])
1048 setValue(groupID, row, col);
1050 setValue(groupID +
" | " + getDataView()[row][col], row, col);
1060 bool TableView::removeRowFromGroup(
const unsigned int& row,
1061 const unsigned int& col,
1062 const std::string& groupNeedle,
1063 bool deleteRowIfNoGroupLeft)
1065 __COUT__ <<
"groupNeedle " << groupNeedle << __E__;
1066 std::set<std::string> groupIDList;
1067 if(!isEntryInGroupCol(row, col, groupNeedle, &groupIDList))
1069 __SS__ <<
"GroupID (" << groupNeedle <<
") removed from row (" << row
1070 <<
") was already removed!" << __E__;
1078 std::string newValue =
"";
1079 unsigned int cnt = 0;
1080 for(
const auto& groupID : groupIDList)
1083 if(groupID == groupNeedle)
1088 newValue += groupID;
1091 bool wasDeleted =
false;
1092 if(deleteRowIfNoGroupLeft && newValue ==
"")
1094 __COUT__ <<
"Delete row since it no longer part of any group." << __E__;
1099 setValue(newValue, row, col);
1112 bool TableView::isEntryInGroup(
const unsigned int& r,
1113 const std::string& childLinkIndex,
1114 const std::string& groupNeedle)
const
1116 unsigned int c = getColLinkGroupID(childLinkIndex);
1118 return isEntryInGroupCol(r, c, groupNeedle);
1130 bool TableView::isEntryInGroupCol(
const unsigned int& r,
1131 const unsigned int& c,
1132 const std::string& groupNeedle,
1133 std::set<std::string>* groupIDList)
const
1142 for(; j < theDataView_[r][c].size(); ++j)
1143 if((theDataView_[r][c][j] ==
' ' ||
1144 theDataView_[r][c][j] ==
'|') &&
1147 else if((theDataView_[r][c][j] ==
1149 theDataView_[r][c][j] ==
'|') &&
1153 groupIDList->emplace(theDataView_[r][c].substr(i, j - i));
1157 if(groupNeedle == theDataView_[r][c].substr(i, j - i))
1170 groupIDList->emplace(theDataView_[r][c].substr(i, j - i));
1174 if(groupNeedle == theDataView_[r][c].substr(i, j - i))
1189 std::set<std::string> TableView::getSetOfGroupIDs(
const std::string& childLinkIndex,
1190 unsigned int r)
const
1192 return getSetOfGroupIDs(getColLinkGroupID(childLinkIndex), r);
1194 std::set<std::string> TableView::getSetOfGroupIDs(
const unsigned int& c,
1195 unsigned int r)
const
1199 std::set<std::string> retSet;
1204 if(r != (
unsigned int)-1)
1206 if(r >= getNumberOfRows())
1208 __SS__ <<
"Invalid row requested!" << __E__;
1212 StringMacros::getSetFromString(theDataView_[r][c], retSet);
1240 for(r = 0; r < getNumberOfRows(); ++r)
1242 StringMacros::getSetFromString(theDataView_[r][c], retSet);
1290 const unsigned int TableView::getColLinkGroupID(
const std::string& childLinkIndex)
const
1292 if(!childLinkIndex.size())
1294 __SS__ <<
"Empty childLinkIndex string parameter!" << __E__;
1298 const char* needleChildLinkIndex = &childLinkIndex[0];
1302 size_t spacePos = childLinkIndex.find(
' ');
1303 if(spacePos != std::string::npos &&
1304 spacePos + 1 < childLinkIndex.size())
1307 needleChildLinkIndex = &childLinkIndex[spacePos + 1];
1310 std::map<std::string, unsigned int>::const_iterator it =
1311 colLinkGroupIDs_.find(needleChildLinkIndex);
1313 colLinkGroupIDs_.end())
1317 <<
"Incompatible table for this group link. Table '" << tableName_
1318 <<
"' is missing a GroupID column with data type '"
1319 << TableViewColumnInfo::TYPE_START_GROUP_ID <<
"-" << needleChildLinkIndex
1321 <<
"Note: you can separate the child GroupID column data type from "
1322 <<
"the parent GroupLink column data type; this is accomplished by using a space "
1323 <<
"character at the parent level - the string after the space will be treated "
1325 <<
"child GroupID column data type." << __E__;
1326 ss <<
"Existing Column GroupIDs: " << __E__;
1327 for(
auto& groupIdColPair : colLinkGroupIDs_)
1328 ss <<
"\t" << groupIdColPair.first <<
" : col-" << groupIdColPair.second << __E__;
1330 ss <<
"Existing Column Types: " << __E__;
1331 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1332 ss <<
"\t" << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1339 unsigned int TableView::findRow(
unsigned int col,
1340 const std::string& value,
1341 unsigned int offsetRow)
const
1343 for(
unsigned int row = offsetRow; row < theDataView_.size(); ++row)
1345 if(theDataView_[row][col] == value)
1349 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find value=" << value
1350 <<
" in column named " << columnsInfo_[col].getName()
1351 <<
" with type=" << columnsInfo_[col].getType() << __E__;
1359 unsigned int TableView::findRowInGroup(
unsigned int col,
1360 const std::string& value,
1361 const std::string& groupId,
1362 const std::string& childLinkIndex,
1363 unsigned int offsetRow)
const
1365 unsigned int groupIdCol = getColLinkGroupID(childLinkIndex);
1366 for(
unsigned int row = offsetRow; row < theDataView_.size(); ++row)
1368 if(theDataView_[row][col] == value && isEntryInGroupCol(row, groupIdCol, groupId))
1372 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find in group the value=" << value
1373 <<
" in column named '" << columnsInfo_[col].getName()
1374 <<
"' with type=" << columnsInfo_[col].getType() <<
" and GroupID: '"
1375 << groupId <<
"' in column '" << groupIdCol
1376 <<
"' with GroupID child link index '" << childLinkIndex <<
"'" << __E__;
1385 unsigned int TableView::findCol(
const std::string& wildCardName)
const
1387 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1388 if(StringMacros::wildCardMatch(wildCardName ,
1389 columnsInfo_[col].getName() ))
1392 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find column named '" << wildCardName
1394 ss <<
"Existing columns:\n";
1395 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1396 ss <<
"\t" << columnsInfo_[col].getName() <<
"\n";
1405 unsigned int TableView::findColByType(
const std::string& type,
int startingCol)
const
1407 for(
unsigned int col = startingCol; col < columnsInfo_.size(); ++col)
1408 if(columnsInfo_[col].getType() == type)
1416 const std::string& TableView::getUniqueStorageIdentifier(
void)
const
1418 return uniqueStorageIdentifier_;
1422 const std::string& TableView::getTableName(
void)
const {
return tableName_; }
1425 const TableVersion& TableView::getVersion(
void)
const {
return version_; }
1428 const std::string& TableView::getComment(
void)
const {
return comment_; }
1431 const std::string& TableView::getAuthor(
void)
const {
return author_; }
1434 const time_t& TableView::getCreationTime(
void)
const {
return creationTime_; }
1437 const time_t& TableView::getLastAccessTime(
void)
const {
return lastAccessTime_; }
1440 const bool& TableView::getLooseColumnMatching(
void)
const
1442 return fillWithLooseColumnMatching_;
1447 const unsigned int TableView::getDataColumnSize(
void)
const
1450 if(!getNumberOfRows())
1451 return getNumberOfColumns();
1452 return theDataView_[0].size();
1458 const unsigned int& TableView::getSourceColumnMismatch(
void)
const
1460 return sourceColumnMismatchCount_;
1466 const unsigned int& TableView::getSourceColumnMissing(
void)
const
1468 return sourceColumnMissingCount_;
1474 const std::set<std::string>& TableView::getSourceColumnNames(
void)
const
1476 return sourceColumnNames_;
1480 std::set<std::string> TableView::getColumnNames(
void)
const
1482 std::set<std::string> retSet;
1483 for(
auto& colInfo : columnsInfo_)
1484 retSet.emplace(colInfo.getName());
1489 std::map<std::string,
unsigned int > TableView::getColumnNamesMap(
void)
const
1491 std::map<std::string,
unsigned int > retMap;
1493 for(
auto& colInfo : columnsInfo_)
1494 retMap.emplace(std::make_pair(colInfo.getName(), c++));
1499 std::set<std::string> TableView::getColumnStorageNames(
void)
const
1501 std::set<std::string> retSet;
1502 for(
auto& colInfo : columnsInfo_)
1503 retSet.emplace(colInfo.getStorageName());
1508 std::vector<std::string> TableView::getDefaultRowValues(
void)
const
1510 std::vector<std::string> retVec;
1513 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
1520 if(columnsInfo_[col].isChildLink())
1522 const std::vector<std::string>& theDataChoices =
1523 columnsInfo_[col].getDataChoices();
1526 if(!theDataChoices.size() ||
1527 theDataChoices[0] ==
"arbitraryBool=1")
1528 retVec.push_back(columnsInfo_[col].getDefaultValue());
1532 (theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=0");
1537 bool foundDefault =
false;
1539 for(
const auto& choice : theDataChoices)
1540 if(skipOne && !hasSkipped)
1545 else if(choice == columnsInfo_[col].getDefaultValue())
1547 foundDefault =
true;
1552 if(!foundDefault && theDataChoices.size() > (skipOne ? 1 : 0))
1553 retVec.push_back(theDataChoices[(skipOne ? 1 : 0)]);
1555 retVec.push_back(columnsInfo_[col].getDefaultValue());
1559 retVec.push_back(columnsInfo_[col].getDefaultValue());
1566 unsigned int TableView::getNumberOfRows(
void)
const {
return theDataView_.size(); }
1569 unsigned int TableView::getNumberOfColumns(
void)
const {
return columnsInfo_.size(); }
1572 const TableView::DataView& TableView::getDataView(
void)
const {
return theDataView_; }
1581 const std::vector<TableViewColumnInfo>& TableView::getColumnsInfo(
void)
const
1583 return columnsInfo_;
1587 std::vector<TableViewColumnInfo>* TableView::getColumnsInfoP(
void)
1589 return &columnsInfo_;
1594 if(column >= columnsInfo_.size())
1596 std::stringstream errMsg;
1597 errMsg << __COUT_HDR_FL__ <<
"\nCan't find column " << column
1598 <<
"\n\n\n\nThe column info is likely missing due to incomplete "
1599 "Configuration View filling.\n\n"
1601 __THROW__(errMsg.str().c_str());
1603 return columnsInfo_[column];
1608 void TableView::setUniqueStorageIdentifier(
const std::string& storageUID)
1610 uniqueStorageIdentifier_ = storageUID;
1614 void TableView::setTableName(
const std::string& name) { tableName_ = name; }
1617 void TableView::setComment(
const std::string& comment) { comment_ = comment; }
1620 void TableView::setURIEncodedComment(
const std::string& uriComment)
1622 comment_ = StringMacros::decodeURIComponent(uriComment);
1626 void TableView::setAuthor(
const std::string& author) { author_ = author; }
1629 void TableView::setCreationTime(time_t t) { creationTime_ = t; }
1632 void TableView::setLastAccessTime(time_t t) { lastAccessTime_ = t; }
1635 void TableView::setLooseColumnMatching(
bool setValue)
1637 fillWithLooseColumnMatching_ = setValue;
1641 void TableView::reset(
void)
1646 columnsInfo_.clear();
1647 theDataView_.clear();
1651 void TableView::print(std::ostream& out)
const
1653 out <<
"============================================================================="
1656 out <<
"Print: " << tableName_ <<
" Version: " << version_ <<
" Comment: " << comment_
1657 <<
" Author: " << author_ <<
" Creation Time: " << ctime(&creationTime_) << __E__;
1658 out <<
"\t\tNumber of Cols " << getNumberOfColumns() << __E__;
1659 out <<
"\t\tNumber of Rows " << getNumberOfRows() << __E__;
1661 out <<
"Columns:\t";
1662 for(
int i = 0; i < (int)columnsInfo_.size(); ++i)
1663 out << i <<
":" << columnsInfo_[i].getName() <<
":"
1664 << columnsInfo_[i].getStorageName() <<
":" << columnsInfo_[i].getType() <<
":"
1665 << columnsInfo_[i].getDataType() <<
"\t ";
1668 out <<
"Rows:" << __E__;
1671 for(
int r = 0; r < (int)getNumberOfRows(); ++r)
1673 out << (int)r <<
":\t";
1674 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
1676 out << (int)c <<
":";
1679 if(columnsInfo_[c].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
1681 int choiceIndex = -1;
1682 std::vector<std::string> choices = columnsInfo_[c].getDataChoices();
1683 val = StringMacros::convertEnvironmentVariables(theDataView_[r][c]);
1685 if(val == columnsInfo_[c].getDefaultValue())
1689 for(
int i = 0; i < (int)choices.size(); ++i)
1690 if(val == choices[i])
1691 choiceIndex = i + 1;
1694 out <<
"ChoiceIndex=" << choiceIndex <<
":";
1697 out << theDataView_[r][c];
1717 void TableView::printJSON(std::ostream& out)
const
1720 out <<
"\"NAME\" : \"" << tableName_ <<
"\",\n";
1724 out <<
"\"COMMENT\" : ";
1730 for(
unsigned int i = 0; i < val.size(); ++i)
1734 else if(val[i] ==
'\t')
1736 else if(val[i] ==
'\r')
1741 if(val[i] ==
'"' || val[i] ==
'\\')
1748 out <<
"\"AUTHOR\" : \"" << author_ <<
"\",\n";
1749 out <<
"\"CREATION_TIME\" : " << creationTime_ <<
",\n";
1754 out <<
"\"COL_TYPES\" : {\n";
1755 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
1757 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1758 out <<
"\"" << columnsInfo_[c].getDataType() <<
"\"";
1759 if(c + 1 < (
int)getNumberOfColumns())
1765 out <<
"\"DATA_SET\" : [\n";
1767 for(
int r = 0; r < (int)getNumberOfRows(); ++r)
1770 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
1772 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1774 out <<
"\"" << getEscapedValueAsString(r, c,
false)
1777 if(c + 1 < (
int)getNumberOfColumns())
1782 if(r + 1 < (
int)getNumberOfRows())
1794 std::string restoreJSONStringEntities(
const std::string& str)
1796 unsigned int sz = str.size();
1800 std::stringstream retStr;
1802 for(; i < sz - 1; ++i)
1834 retStr << str[sz - 1];
1836 return retStr.str();
1847 int TableView::fillFromJSON(
const std::string& json)
1849 std::vector<std::string> keys;
1850 keys.push_back(
"NAME");
1851 keys.push_back(
"COMMENT");
1852 keys.push_back(
"AUTHOR");
1853 keys.push_back(
"CREATION_TIME");
1855 keys.push_back(
"DATA_SET");
1859 CV_JSON_FILL_COMMENT,
1860 CV_JSON_FILL_AUTHOR,
1861 CV_JSON_FILL_CREATION_TIME,
1863 CV_JSON_FILL_DATA_SET
1868 sourceColumnMismatchCount_ = 0;
1869 sourceColumnMissingCount_ = 0;
1870 sourceColumnNames_.clear();
1871 unsigned int colFoundCount = 0;
1873 unsigned int row = -1;
1874 unsigned int colSpeedup = 0;
1875 unsigned int startString, startNumber, endNumber = -1;
1876 unsigned int bracketCount = 0;
1877 unsigned int sqBracketCount = 0;
1881 bool isDataArray = 0;
1882 bool keyIsMatch, keyIsComment;
1883 unsigned int keyIsMatchIndex, keyIsMatchStorageIndex, keyIsMatchCommentIndex;
1884 const std::string COMMENT_ALT_KEY =
"COMMENT";
1886 std::string extractedString =
"", currKey =
"", currVal =
"";
1887 unsigned int currDepth;
1889 std::vector<std::string> jsonPath;
1890 std::vector<char> jsonPathType;
1891 char lastPopType =
'_';
1893 unsigned int matchedKey = -1;
1894 unsigned int lastCol = -1;
1897 for(; i < json.size(); ++i)
1902 if(i - 1 < json.size() &&
1903 json[i - 1] ==
'\\')
1906 inQuotes = !inQuotes;
1911 extractedString = restoreJSONStringEntities(
1912 json.substr(startString + 1, i - startString - 1));
1921 if(jsonPathType[jsonPathType.size() - 1] !=
'{' ||
1924 __COUT__ <<
"Invalid ':' position" << __E__;
1929 jsonPathType.push_back(
'K');
1930 jsonPath.push_back(extractedString);
1949 if(lastPopType ==
'{')
1952 if(jsonPathType[jsonPathType.size() - 1] ==
'K')
1955 jsonPath.pop_back();
1956 jsonPathType.pop_back();
1962 currVal = extractedString;
1965 if(endNumber == (
unsigned int)-1 ||
1966 endNumber <= startNumber)
1969 if(endNumber <= startNumber)
1972 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
1975 currDepth = bracketCount;
1977 if(jsonPathType[jsonPathType.size() - 1] ==
'K')
1979 currKey = jsonPath[jsonPathType.size() - 1];
1984 jsonPath.pop_back();
1985 jsonPathType.pop_back();
1987 else if(jsonPathType[jsonPathType.size() - 1] ==
1991 for(
unsigned int k = jsonPathType.size() - 2; k < jsonPathType.size();
1993 if(jsonPathType[k] ==
'K')
1995 currKey = jsonPath[k];
2000 __COUT__ <<
"Invalid array position" << __E__;
2009 __COUT__ <<
"Invalid ',' position" << __E__;
2020 jsonPathType.push_back(
'{');
2021 jsonPath.push_back(
"{");
2034 if(lastPopType !=
'{' &&
2035 jsonPathType[jsonPathType.size() - 1] ==
'K')
2037 currDepth = bracketCount;
2038 currKey = jsonPath[jsonPathType.size() - 1];
2040 currVal = extractedString;
2043 if(endNumber == (
unsigned int)-1 ||
2044 endNumber <= startNumber)
2047 if(endNumber <= startNumber)
2051 json.substr(startNumber + 1, endNumber - startNumber - 1);
2055 jsonPath.pop_back();
2056 jsonPathType.pop_back();
2059 if(jsonPathType[jsonPathType.size() - 1] !=
'{')
2061 __COUT__ <<
"Invalid '}' position" << __E__;
2065 jsonPath.pop_back();
2066 jsonPathType.pop_back();
2072 jsonPathType.push_back(
'[');
2073 jsonPath.push_back(
"[");
2082 if(jsonPathType[jsonPathType.size() - 1] !=
'[')
2084 __COUT__ <<
"Invalid ']' position" << __E__;
2088 currDepth = bracketCount;
2092 currVal = extractedString;
2095 if(endNumber == (
unsigned int)-1 ||
2096 endNumber <= startNumber)
2099 if(endNumber <= startNumber)
2102 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
2107 for(
unsigned int k = jsonPathType.size() - 2; k < jsonPathType.size(); --k)
2108 if(jsonPathType[k] ==
'K')
2110 currKey = jsonPath[k];
2115 __COUT__ <<
"Invalid array position" << __E__;
2120 if(jsonPathType[jsonPathType.size() - 1] !=
'[')
2122 __COUT__ <<
"Invalid ']' position" << __E__;
2126 jsonPath.pop_back();
2127 jsonPathType.pop_back();
2136 if(startNumber != (
unsigned int)-1 && endNumber == (
unsigned int)-1)
2145 std::cout << i <<
":\t" << json[i] <<
" - ";
2147 std::cout <<
"ExtKey=";
2148 for(
unsigned int k = 0; k < jsonPath.size(); ++k)
2149 std::cout << jsonPath[k] <<
"/";
2151 std::cout << lastPopType <<
" ";
2152 std::cout << bracketCount <<
" ";
2153 std::cout << sqBracketCount <<
" ";
2154 std::cout << inQuotes <<
" ";
2155 std::cout << newValue <<
"-";
2156 std::cout << currKey <<
"-{" << currDepth <<
"}:";
2157 std::cout << currVal <<
" ";
2158 std::cout << startNumber <<
"-";
2159 std::cout << endNumber <<
" ";
2189 for(
unsigned int k = 0; k < keys.size(); ++k)
2190 if((currDepth == 1 && keys[k] == currKey) ||
2191 (currDepth > 1 && keys[k] == jsonPath[1]))
2194 if(matchedKey != (
unsigned int)-1)
2201 case CV_JSON_FILL_NAME:
2203 setTableName(currVal);
2205 case CV_JSON_FILL_COMMENT:
2207 setComment(currVal);
2209 case CV_JSON_FILL_AUTHOR:
2213 case CV_JSON_FILL_CREATION_TIME:
2215 setCreationTime(strtol(currVal.c_str(), 0, 10));
2220 case CV_JSON_FILL_DATA_SET:
2232 unsigned int col, ccnt = 0;
2233 unsigned int noc = getNumberOfColumns();
2234 for(; ccnt < noc; ++ccnt)
2240 if(fillWithLooseColumnMatching_)
2253 if(getNumberOfRows() == 1)
2254 sourceColumnNames_.emplace(currKey);
2258 if(row >= getNumberOfRows())
2260 __SS__ <<
"Invalid row"
2262 std::cout << ss.str();
2267 theDataView_[row][col] =
2275 col = (ccnt + colSpeedup) % noc;
2281 keyIsComment =
true;
2282 for(keyIsMatchIndex = 0,
2283 keyIsMatchStorageIndex = 0,
2284 keyIsMatchCommentIndex = 0;
2285 keyIsMatchIndex < currKey.size();
2288 if(columnsInfo_[col]
2289 .getStorageName()[keyIsMatchStorageIndex] ==
2291 ++keyIsMatchStorageIndex;
2293 if(currKey[keyIsMatchIndex] ==
'_')
2297 if(keyIsMatchStorageIndex >=
2298 columnsInfo_[col].getStorageName().size() ||
2299 currKey[keyIsMatchIndex] !=
2301 .getStorageName()[keyIsMatchStorageIndex])
2311 keyIsMatchCommentIndex < COMMENT_ALT_KEY.size())
2313 if(currKey[keyIsMatchIndex] !=
2314 COMMENT_ALT_KEY[keyIsMatchCommentIndex])
2317 keyIsComment =
false;
2321 ++keyIsMatchStorageIndex;
2332 if(getNumberOfRows())
2333 sourceColumnMissingCount_ +=
2334 getNumberOfColumns() - colFoundCount;
2342 if(getNumberOfRows() == 1)
2343 sourceColumnNames_.emplace(currKey);
2347 if(row >= getNumberOfRows())
2349 __SS__ <<
"Invalid row"
2351 __COUT__ <<
"\n" << ss.str();
2356 theDataView_[row][col] = currVal;
2366 if(ccnt >= getNumberOfColumns())
2369 <<
"\n\nInvalid column in JSON source data: " << currKey
2370 <<
" not found in column names of table named "
2371 << getTableName() <<
"."
2373 __COUT__ <<
"\n" << ss.str();
2376 ++sourceColumnMismatchCount_;
2377 if(getNumberOfRows() == 1)
2378 sourceColumnNames_.emplace(currKey);
2382 <<
"Ignoring error, and not populating missing column."
2410 bool TableView::isURIEncodedCommentTheSame(
const std::string& comment)
const
2412 std::string compareStr = StringMacros::decodeURIComponent(comment);
2413 return comment_ == compareStr;
2472 int TableView::fillFromCSV(
const std::string& data,
2473 const int& dataOffset,
2474 const std::string& author)
2482 int j = data.find(
',', i);
2483 int k = data.find(
';', i);
2485 bool rowWasModified;
2486 unsigned int countRowsModified = 0;
2487 int authorCol = findColByType(TableViewColumnInfo::TYPE_AUTHOR);
2488 int timestampCol = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
2491 while(k != (
int)(std::string::npos))
2493 rowWasModified =
false;
2494 if(r >= (
int)getNumberOfRows())
2498 rowWasModified =
true;
2501 while(j < k && j != (
int)(std::string::npos))
2506 if(c >= (
int)getNumberOfColumns() - 2)
2509 j = data.find(
',', i);
2514 if(setURIEncodedValue(data.substr(i, j - i), r, c))
2515 rowWasModified =
true;
2518 j = data.find(
',', i);
2523 if(author !=
"" && rowWasModified)
2525 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << __E__;
2526 setValue(author, r, authorCol);
2527 setValue(time(0), r, timestampCol);
2531 ++countRowsModified;
2537 j = data.find(
',', i);
2538 k = data.find(
';', i);
2542 while(r < (
int)getNumberOfRows())
2545 __COUT__ <<
"Row deleted: " << (int)r << __E__;
2546 ++countRowsModified;
2549 __COUT_INFO__ <<
"countRowsModified=" << countRowsModified << __E__;
2551 if(!countRowsModified)
2556 bool match = getColumnStorageNames().size() == getSourceColumnNames().size();
2559 for(
auto& destColName : getColumnStorageNames())
2560 if(getSourceColumnNames().find(destColName) ==
2561 getSourceColumnNames().end())
2563 __COUT__ <<
"Found column name mismach for '" << destColName
2564 <<
"'... So allowing same data!" << __E__;
2573 __SS__ <<
"No rows were modified! No reason to fill a view with same content."
2575 __COUT__ <<
"\n" << ss.str();
2585 sourceColumnNames_.clear();
2586 for(
unsigned int i = 0; i < getNumberOfColumns(); ++i)
2587 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
2608 bool TableView::setURIEncodedValue(
const std::string& value,
2609 const unsigned int& r,
2610 const unsigned int& c,
2611 const std::string& author)
2613 if(!(c < columnsInfo_.size() && r < getNumberOfRows()))
2615 __SS__ <<
"Invalid row (" << (int)r <<
") col (" << (
int)c << ") requested!"
2616 << "Number of Rows = " << getNumberOfRows()
2617 << "Number of Columns = " << columnsInfo_.size() << __E__;
2622 std::
string valueStr =
StringMacros::decodeURIComponent(value);
2623 std::
string originalValueStr =
2624 getValueAsString(r, c, false);
2632 std::string convertedString = StringMacros::convertEnvironmentVariables(valueStr);
2647 theDataView_[r][c] = valueStr;
2649 else if(columnsInfo_[c].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
2661 setValue(time_t(strtol(valueStr.c_str(), 0, 10)), r, c);
2664 theDataView_[r][c] = valueStr;
2666 bool rowWasModified =
2667 (originalValueStr !=
2668 getValueAsString(r, c,
false));
2671 if(author !=
"" && rowWasModified)
2673 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << __E__;
2674 int authorCol = findColByType(TableViewColumnInfo::TYPE_AUTHOR);
2675 int timestampCol = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
2676 setValue(author, r, authorCol);
2677 setValue(time(0), r, timestampCol);
2680 return rowWasModified;
2684 void TableView::resizeDataView(
unsigned int nRows,
unsigned int nCols)
2688 theDataView_.resize(nRows, std::vector<std::string>(nCols));
2698 unsigned int TableView::addRow(
const std::string& author,
2699 bool incrementUniqueData,
2700 std::string baseNameAutoUID,
2701 unsigned int rowToAdd)
2704 if(rowToAdd == (
unsigned int)-1)
2705 rowToAdd = getNumberOfRows();
2707 theDataView_.resize(getNumberOfRows() + 1,
2708 std::vector<std::string>(getNumberOfColumns()));
2711 for(
unsigned int r = getNumberOfRows() - 2; r >= rowToAdd; --r)
2713 if(r == (
unsigned int)-1)
2715 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
2716 theDataView_[r + 1][col] = theDataView_[r][col];
2719 std::vector<std::string> defaultRowValues = getDefaultRowValues();
2721 char indexString[1000];
2722 std::string tmpString, baseString;
2725 unsigned int maxUniqueData;
2726 std::string numString;
2731 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
2738 if(incrementUniqueData &&
2739 (col == getColUID() ||
2740 (getNumberOfRows() > 1 &&
2741 (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_DATA ||
2742 columnsInfo_[col].getType() ==
2743 TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA))))
2759 for(
unsigned int r = 0; r < getNumberOfRows(); ++r)
2767 tmpString = theDataView_[r][col];
2771 for(index = tmpString.length() - 1; index < tmpString.length(); --index)
2775 if(!(tmpString[index] >=
'0' && tmpString[index] <=
'9'))
2782 if(tmpString.length() && foundAny)
2785 numString = tmpString.substr(index + 1);
2786 tmpString = tmpString.substr(0, index + 1);
2793 sscanf(numString.c_str(),
"%u", &index);
2795 if(index > maxUniqueData)
2797 maxUniqueData = index;
2798 baseString = tmpString;
2805 sprintf(indexString,
"%u", maxUniqueData);
2809 if(col == getColUID())
2812 if(baseNameAutoUID !=
"")
2813 theDataView_[rowToAdd][col] = baseNameAutoUID + indexString;
2815 theDataView_[rowToAdd][col] = baseString + indexString;
2818 theDataView_[rowToAdd][col] = baseString + indexString;
2820 __COUT__ <<
"New unique data entry is data[" << rowToAdd <<
"][" << col
2821 <<
"] = '" << theDataView_[rowToAdd][col] <<
"'" << __E__;
2826 theDataView_[rowToAdd][col] = defaultRowValues[col];
2831 __COUT__ <<
"Row=" << rowToAdd <<
" was created!" << __E__;
2832 int authorCol = findColByType(TableViewColumnInfo::TYPE_AUTHOR);
2833 int timestampCol = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
2834 setValue(author, rowToAdd, authorCol);
2835 setValue(time(0), rowToAdd, timestampCol);
2844 void TableView::deleteRow(
int r)
2846 if(r >= (
int)getNumberOfRows())
2849 __SS__ <<
"Row " << (int)r
2850 <<
" is out of bounds (Row Count = " << getNumberOfRows()
2851 <<
") and can not be deleted." << __E__;
2855 theDataView_.erase(theDataView_.begin() + r);
2874 const bool TableView::getChildLink(
2875 const unsigned int& c,
2877 std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>& linkPair)
const
2879 if(!(c < columnsInfo_.size()))
2881 __SS__ <<
"Invalid col (" << (int)c <<
") requested!" << __E__;
2889 if((isGroup = columnsInfo_[c].isChildLinkGroupID()) ||
2890 columnsInfo_[c].isChildLinkUID())
2894 linkPair.second = c;
2895 std::string index = columnsInfo_[c].getChildLinkIndex();
2900 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
2906 else if(columnsInfo_[col].isChildLink() &&
2907 index == columnsInfo_[col].getChildLinkIndex())
2912 linkPair.first = col;
2918 __SS__ <<
"\tIn view: " << tableName_
2919 <<
", Can't find complete child link for column name "
2920 << columnsInfo_[c].getName() << __E__;
2924 if(!columnsInfo_[c].isChildLink())
2929 std::string index = columnsInfo_[c].getChildLinkIndex();
2934 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
2951 if(((columnsInfo_[col].isChildLinkUID() && !(isGroup =
false)) ||
2952 (columnsInfo_[col].isChildLinkGroupID() && (isGroup =
true))) &&
2953 index == columnsInfo_[col].getChildLinkIndex())
2958 linkPair.second = col;
2964 __SS__ <<
"\tIn view: " << tableName_
2965 <<
", Can't find complete child link id for column name "
2966 << columnsInfo_[c].getName() << __E__;