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() !=
"CommentDescription")
187 __SS__ <<
"Table Error:\t" << TableViewColumnInfo::TYPE_COMMENT
188 <<
" data type column must have name="
189 <<
"CommentDescription" << __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__ <<
"Table 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__ <<
"Table Error:\t'" << theDataView_[row][col]
512 <<
"' in column " << columnsInfo_[col].getName()
513 <<
" is not a valid Fixed Choice option. "
514 <<
"Possible values are as follows: ";
519 for(
unsigned int i = skipOne ? 1 : 0;
520 i < columnsInfo_[col].getDataChoices().size();
523 if(i > (skipOne ? 1 : 0))
525 ss << columnsInfo_[col].getDataChoices()[i];
532 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_ON_OFF)
533 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
535 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" ||
536 theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
537 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_ON;
538 else if(theDataView_[row][col] ==
"0" ||
539 theDataView_[row][col] ==
"off" ||
540 theDataView_[row][col] ==
"Off" ||
541 theDataView_[row][col] ==
"OFF")
542 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_OFF;
545 __SS__ <<
"Table Error:\t" << theDataView_[row][col]
546 <<
" in column " << columnsInfo_[col].getName()
547 <<
" is not a valid Type (On/Off) std::string. Possible "
548 "values are 1, on, On, ON, 0, off, Off, OFF."
553 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_TRUE_FALSE)
554 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
556 if(theDataView_[row][col] ==
"1" ||
557 theDataView_[row][col] ==
"true" ||
558 theDataView_[row][col] ==
"True" ||
559 theDataView_[row][col] ==
"TRUE")
560 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_TRUE;
561 else if(theDataView_[row][col] ==
"0" ||
562 theDataView_[row][col] ==
"false" ||
563 theDataView_[row][col] ==
"False" ||
564 theDataView_[row][col] ==
"FALSE")
565 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_FALSE;
568 __SS__ <<
"Table Error:\t" << theDataView_[row][col]
569 <<
" in column " << columnsInfo_[col].getName()
570 <<
" is not a valid Type (True/False) std::string. "
571 "Possible values are 1, true, True, TRUE, 0, false, "
577 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_YES_NO)
578 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
580 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" ||
581 theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
582 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_YES;
583 else if(theDataView_[row][col] ==
"0" ||
584 theDataView_[row][col] ==
"no" ||
585 theDataView_[row][col] ==
"No" ||
586 theDataView_[row][col] ==
"NO")
587 theDataView_[row][col] = TableViewColumnInfo::TYPE_VALUE_NO;
590 __SS__ <<
"Table Error:\t" << theDataView_[row][col]
591 <<
" in column " << columnsInfo_[col].getName()
592 <<
" is not a valid Type (Yes/No) std::string. Possible "
593 "values are 1, yes, Yes, YES, 0, no, No, NO."
598 else if(columnsInfo_[col].isGroupID())
600 colLinkGroupIDs_[columnsInfo_[col].getChildLinkIndex()] =
603 groupIdIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
604 ++groupIdIndexesCount;
606 else if(columnsInfo_[col].isChildLink())
609 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
610 if(theDataView_[row][col] ==
"NoLink" ||
611 theDataView_[row][col] ==
"No_Link" ||
612 theDataView_[row][col] ==
"NOLINK" ||
613 theDataView_[row][col] ==
"NO_LINK" ||
614 theDataView_[row][col] ==
"Nolink" ||
615 theDataView_[row][col] ==
"nolink" ||
616 theDataView_[row][col] ==
"noLink")
617 theDataView_[row][col] =
618 TableViewColumnInfo::DATATYPE_LINK_DEFAULT;
621 childLinkIndexes.emplace(columnsInfo_[col].getChildLinkIndex());
622 ++childLinkIndexesCount;
625 if(columnsInfo_[col].getDataType() !=
626 TableViewColumnInfo::DATATYPE_STRING)
628 __SS__ <<
"Table Error:\t"
629 <<
"Column " << col <<
" with name "
630 << columnsInfo_[col].getName()
631 <<
" is a Child Link column and has an illegal data type of '"
632 << columnsInfo_[col].getDataType()
633 <<
"'. The data type for Child Link columns must be "
634 << TableViewColumnInfo::DATATYPE_STRING << __E__;
639 getChildLink(col, tmpIsGroup, tmpLinkPair);
641 else if(columnsInfo_[col].isChildLinkUID() ||
642 columnsInfo_[col].isChildLinkGroupID())
645 childLinkIdLabels.emplace(columnsInfo_[col].getChildLinkIndex());
646 ++childLinkIdLabelsCount;
649 for(
unsigned int row = 0; row < getNumberOfRows(); ++row)
650 if(theDataView_[row][col] ==
"")
651 theDataView_[row][col] = rowDefaults[col];
654 getChildLink(col, tmpIsGroup, tmpLinkPair);
659 if(groupIdIndexes.size() != groupIdIndexesCount)
661 __SS__ << (
"GroupId Labels are not unique!") <<
"There are "
662 << groupIdIndexesCount <<
" GroupId Labels and the unique count is "
663 << groupIdIndexes.size() << __E__;
666 if(childLinkIndexes.size() != childLinkIndexesCount)
668 __SS__ << (
"Child Link Labels are not unique!") <<
"There are "
669 << childLinkIndexesCount
670 <<
" Child Link Labels and the unique count is "
671 << childLinkIndexes.size() << __E__;
674 if(childLinkIdLabels.size() != childLinkIdLabelsCount)
676 __SS__ << (
"Child Link ID Labels are not unique!") <<
"There are "
677 << childLinkIdLabelsCount
678 <<
" Child Link ID Labels and the unique count is "
679 << childLinkIdLabels.size() << __E__;
685 __COUT__ <<
"Error occured in TableView::init() for version=" << version_
696 void TableView::getValue(std::string& value,
699 bool doConvertEnvironmentVariables)
const
701 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
703 __SS__ <<
"Invalid row col requested" << __E__;
707 value = validateValueForColumn(
708 theDataView_[row][col], col, doConvertEnvironmentVariables);
716 std::string TableView::validateValueForColumn(
const std::string& value,
718 bool doConvertEnvironmentVariables)
const
720 if(col >= columnsInfo_.size())
722 __SS__ <<
"Invalid col requested" << __E__;
726 if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_STRING)
727 return doConvertEnvironmentVariables
728 ? StringMacros::convertEnvironmentVariables(value)
730 else if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
732 return StringMacros::getTimestampString(
733 doConvertEnvironmentVariables
734 ? StringMacros::convertEnvironmentVariables(value)
748 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
749 <<
" in configuration " << tableName_
750 <<
" at column=" << columnsInfo_[col].getName()
751 <<
" for getValue with type '"
752 << StringMacros::demangleTypeName(
typeid(std::string).name()) <<
"'"
764 std::string TableView::getValueAsString(
unsigned int row,
766 bool doConvertEnvironmentVariables)
const
768 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
770 __SS__ << (
"Invalid row col requested") << __E__;
776 if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_ON_OFF)
778 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"on" ||
779 theDataView_[row][col] ==
"On" || theDataView_[row][col] ==
"ON")
780 return TableViewColumnInfo::TYPE_VALUE_ON;
782 return TableViewColumnInfo::TYPE_VALUE_OFF;
784 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_TRUE_FALSE)
786 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"true" ||
787 theDataView_[row][col] ==
"True" || theDataView_[row][col] ==
"TRUE")
788 return TableViewColumnInfo::TYPE_VALUE_TRUE;
790 return TableViewColumnInfo::TYPE_VALUE_FALSE;
792 else if(columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_YES_NO)
794 if(theDataView_[row][col] ==
"1" || theDataView_[row][col] ==
"yes" ||
795 theDataView_[row][col] ==
"Yes" || theDataView_[row][col] ==
"YES")
796 return TableViewColumnInfo::TYPE_VALUE_YES;
798 return TableViewColumnInfo::TYPE_VALUE_NO;
802 return doConvertEnvironmentVariables
803 ? StringMacros::convertEnvironmentVariables(theDataView_[row][col])
804 : theDataView_[row][col];
813 std::string TableView::getEscapedValueAsString(
unsigned int row,
815 bool doConvertEnvironmentVariables)
const
817 std::string val = getValueAsString(row, col, doConvertEnvironmentVariables);
818 std::string retVal =
"";
819 retVal.reserve(val.size());
820 for(
unsigned int i = 0; i < val.size(); ++i)
824 else if(val[i] ==
'\t')
826 else if(val[i] ==
'\r')
831 if(val[i] ==
'"' || val[i] ==
'\\')
842 void TableView::setValue(
const std::string& value,
unsigned int row,
unsigned int col)
844 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
846 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
850 if(columnsInfo_[col].getDataType() == TableViewColumnInfo::DATATYPE_STRING)
851 theDataView_[row][col] = value;
855 __SS__ <<
"\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
856 <<
" in configuration " << tableName_
857 <<
" at column=" << columnsInfo_[col].getName()
858 <<
" for setValue with type '"
859 << StringMacros::demangleTypeName(
typeid(value).name()) <<
"'" << __E__;
863 void TableView::setValue(
const char* value,
unsigned int row,
unsigned int col)
865 setValue(std::string(value), row, col);
871 void TableView::setValueAsString(
const std::string& value,
875 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
877 __SS__ <<
"Invalid row (" << row <<
") col (" << col <<
") requested!" << __E__;
881 theDataView_[row][col] = value;
887 const unsigned int TableView::getOrInitColUID(
void)
889 if(colUID_ != INVALID)
893 colUID_ = findColByType(TableViewColumnInfo::TYPE_UID);
894 if(colUID_ == INVALID)
896 __COUT__ <<
"Column Types: " << __E__;
897 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
898 std::cout << columnsInfo_[col].getType() <<
"() "
899 << columnsInfo_[col].getName() << __E__;
900 __SS__ <<
"\tMissing UID Column in table named '" << tableName_ <<
"'" << __E__;
909 const unsigned int TableView::getColUID(
void)
const
911 if(colUID_ != INVALID)
914 __COUT__ <<
"Column Types: " << __E__;
915 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
916 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
919 __SS__ << (
"Missing UID Column in config named " + tableName_ +
920 ". (Possibly TableView was just not initialized?" +
921 "This is the const call so can not alter class members)")
929 const unsigned int TableView::getOrInitColStatus(
void)
931 if(colStatus_ != INVALID)
935 colStatus_ = findCol(TableViewColumnInfo::COL_NAME_STATUS);
936 if(colStatus_ == INVALID)
938 __SS__ <<
"\tMissing " << TableViewColumnInfo::COL_NAME_STATUS
939 <<
" Column in table named '" << tableName_ <<
"'" << __E__;
940 ss <<
"Column Types: " << __E__;
941 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
942 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
953 const unsigned int TableView::getOrInitColPriority(
void)
955 if(colPriority_ != INVALID)
960 findCol(
"*" + TableViewColumnInfo::COL_NAME_PRIORITY);
961 if(colPriority_ == INVALID)
963 __SS__ <<
"\tMissing " << TableViewColumnInfo::COL_NAME_PRIORITY
964 <<
" Column in table named '" << tableName_ <<
"'" << __E__;
965 ss <<
"Column Types: " << __E__;
966 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
967 ss << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
979 const unsigned int TableView::getColStatus(
void)
const
981 if(colStatus_ != INVALID)
984 __COUT__ <<
"Column Types: " << __E__;
985 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
986 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
989 __SS__ <<
"Missing " << TableViewColumnInfo::COL_NAME_STATUS
990 <<
" Column in config named " << tableName_
991 <<
". (Possibly TableView was just not initialized?"
992 <<
"This is the const call so can not alter class members)" << __E__;
1000 const unsigned int TableView::getColPriority(
void)
const
1002 if(colPriority_ != INVALID)
1003 return colPriority_;
1005 __COUT__ <<
"Column Types: " << __E__;
1006 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1007 std::cout << columnsInfo_[col].getType() <<
"() " << columnsInfo_[col].getName()
1010 __SS__ <<
"Missing " << TableViewColumnInfo::COL_NAME_PRIORITY
1011 <<
" Column in config named " << tableName_
1012 <<
". (The Priority column is identified when TableView is initialized)"
1021 void TableView::addRowToGroup(
1022 const unsigned int& row,
1023 const unsigned int& col,
1024 const std::string& groupID)
1027 if(isEntryInGroupCol(row, col, groupID))
1029 __SS__ <<
"GroupID (" << groupID <<
") added to row (" << row
1030 <<
" is already present!" << __E__;
1039 if(getDataView()[row][col] ==
"" ||
1040 getDataView()[row][col] == getDefaultRowValues()[col])
1041 setValue(groupID, row, col);
1043 setValue(groupID +
" | " + getDataView()[row][col], row, col);
1053 bool TableView::removeRowFromGroup(
const unsigned int& row,
1054 const unsigned int& col,
1055 const std::string& groupNeedle,
1056 bool deleteRowIfNoGroupLeft)
1058 __COUT__ <<
"groupNeedle " << groupNeedle << __E__;
1059 std::set<std::string> groupIDList;
1060 if(!isEntryInGroupCol(row, col, groupNeedle, &groupIDList))
1062 __SS__ <<
"GroupID (" << groupNeedle <<
") removed from row (" << row
1063 <<
") was already removed!" << __E__;
1071 std::string newValue =
"";
1072 unsigned int cnt = 0;
1073 for(
const auto& groupID : groupIDList)
1076 if(groupID == groupNeedle)
1081 newValue += groupID;
1084 bool wasDeleted =
false;
1085 if(deleteRowIfNoGroupLeft && newValue ==
"")
1087 __COUT__ <<
"Delete row since it no longer part of any group." << __E__;
1092 setValue(newValue, row, col);
1105 bool TableView::isEntryInGroup(
const unsigned int& r,
1106 const std::string& childLinkIndex,
1107 const std::string& groupNeedle)
const
1109 unsigned int c = getColLinkGroupID(childLinkIndex);
1111 return isEntryInGroupCol(r, c, groupNeedle);
1123 bool TableView::isEntryInGroupCol(
const unsigned int& r,
1124 const unsigned int& c,
1125 const std::string& groupNeedle,
1126 std::set<std::string>* groupIDList)
const
1135 for(; j < theDataView_[r][c].size(); ++j)
1136 if((theDataView_[r][c][j] ==
' ' ||
1137 theDataView_[r][c][j] ==
'|') &&
1140 else if((theDataView_[r][c][j] ==
1142 theDataView_[r][c][j] ==
'|') &&
1146 groupIDList->emplace(theDataView_[r][c].substr(i, j - i));
1150 if(groupNeedle == theDataView_[r][c].substr(i, j - i))
1163 groupIDList->emplace(theDataView_[r][c].substr(i, j - i));
1167 if(groupNeedle == theDataView_[r][c].substr(i, j - i))
1182 std::set<std::string> TableView::getSetOfGroupIDs(
const std::string& childLinkIndex,
1183 unsigned int r)
const
1185 return getSetOfGroupIDs(getColLinkGroupID(childLinkIndex), r);
1187 std::set<std::string> TableView::getSetOfGroupIDs(
const unsigned int& c,
1188 unsigned int r)
const
1192 std::set<std::string> retSet;
1197 if(r != (
unsigned int)-1)
1199 if(r >= getNumberOfRows())
1201 __SS__ <<
"Invalid row requested!" << __E__;
1205 StringMacros::getSetFromString(theDataView_[r][c], retSet);
1233 for(r = 0; r < getNumberOfRows(); ++r)
1235 StringMacros::getSetFromString(theDataView_[r][c], retSet);
1283 const unsigned int TableView::getColLinkGroupID(
const std::string& childLinkIndex)
const
1285 if(!childLinkIndex.size())
1287 __SS__ <<
"Empty childLinkIndex string parameter!" << __E__;
1291 const char* needleChildLinkIndex = &childLinkIndex[0];
1295 size_t spacePos = childLinkIndex.find(
' ');
1296 if(spacePos != std::string::npos &&
1297 spacePos + 1 < childLinkIndex.size())
1300 needleChildLinkIndex = &childLinkIndex[spacePos + 1];
1303 std::map<std::string, unsigned int>::const_iterator it =
1304 colLinkGroupIDs_.find(needleChildLinkIndex);
1306 colLinkGroupIDs_.end())
1309 __COUT__ <<
"Existing Column GroupIDs: " << __E__;
1310 for(
auto& groupIdColPair : colLinkGroupIDs_)
1311 std::cout <<
"\t" << groupIdColPair.first <<
" : col-" << groupIdColPair.second
1314 __COUT__ <<
"Existing Column Types: " << __E__;
1315 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1316 std::cout <<
"\t" << columnsInfo_[col].getType() <<
"() "
1317 << columnsInfo_[col].getName() << __E__;
1320 <<
"Incompatible table for this group link. Table '" << tableName_
1321 <<
"' is missing a GroupID column with data type '"
1322 << TableViewColumnInfo::TYPE_START_GROUP_ID <<
"-" << needleChildLinkIndex
1324 <<
"Note: you can separate the child GroupID column data type from "
1325 <<
"the parent GroupLink column data type; this is accomplished by using a space "
1326 <<
"character at the parent level - the string after the space will be treated "
1328 <<
"child GroupID column data type." << __E__;
1333 unsigned int TableView::findRow(
unsigned int col,
1334 const std::string& value,
1335 unsigned int offsetRow)
const
1337 for(
unsigned int row = offsetRow; row < theDataView_.size(); ++row)
1339 if(theDataView_[row][col] == value)
1343 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find value=" << value
1344 <<
" in column named " << columnsInfo_[col].getName()
1345 <<
" with type=" << columnsInfo_[col].getType() << __E__;
1353 unsigned int TableView::findRowInGroup(
unsigned int col,
1354 const std::string& value,
1355 const std::string& groupId,
1356 const std::string& childLinkIndex,
1357 unsigned int offsetRow)
const
1359 unsigned int groupIdCol = getColLinkGroupID(childLinkIndex);
1360 for(
unsigned int row = offsetRow; row < theDataView_.size(); ++row)
1362 if(theDataView_[row][col] == value && isEntryInGroupCol(row, groupIdCol, groupId))
1366 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find in group the value=" << value
1367 <<
" in column named '" << columnsInfo_[col].getName()
1368 <<
"' with type=" << columnsInfo_[col].getType() <<
" and GroupID: '"
1369 << groupId <<
"' in column '" << groupIdCol
1370 <<
"' with GroupID child link index '" << childLinkIndex <<
"'" << __E__;
1379 unsigned int TableView::findCol(
const std::string& wildCardName)
const
1381 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1382 if(StringMacros::wildCardMatch(wildCardName ,
1383 columnsInfo_[col].getName() ))
1386 __SS__ <<
"\tIn view: " << tableName_ <<
", Can't find column named '" << wildCardName
1388 ss <<
"Existing columns:\n";
1389 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
1390 ss <<
"\t" << columnsInfo_[col].getName() <<
"\n";
1399 unsigned int TableView::findColByType(
const std::string& type,
int startingCol)
const
1401 for(
unsigned int col = startingCol; col < columnsInfo_.size(); ++col)
1402 if(columnsInfo_[col].getType() == type)
1410 const std::string& TableView::getUniqueStorageIdentifier(
void)
const
1412 return uniqueStorageIdentifier_;
1416 const std::string& TableView::getTableName(
void)
const {
return tableName_; }
1419 const TableVersion& TableView::getVersion(
void)
const {
return version_; }
1422 const std::string& TableView::getComment(
void)
const {
return comment_; }
1425 const std::string& TableView::getAuthor(
void)
const {
return author_; }
1428 const time_t& TableView::getCreationTime(
void)
const {
return creationTime_; }
1431 const time_t& TableView::getLastAccessTime(
void)
const {
return lastAccessTime_; }
1434 const bool& TableView::getLooseColumnMatching(
void)
const
1436 return fillWithLooseColumnMatching_;
1441 const unsigned int TableView::getDataColumnSize(
void)
const
1444 if(!getNumberOfRows())
1445 return getNumberOfColumns();
1446 return theDataView_[0].size();
1452 const unsigned int& TableView::getSourceColumnMismatch(
void)
const
1454 return sourceColumnMismatchCount_;
1460 const unsigned int& TableView::getSourceColumnMissing(
void)
const
1462 return sourceColumnMissingCount_;
1468 const std::set<std::string>& TableView::getSourceColumnNames(
void)
const
1470 return sourceColumnNames_;
1474 std::set<std::string> TableView::getColumnNames(
void)
const
1476 std::set<std::string> retSet;
1477 for(
auto& colInfo : columnsInfo_)
1478 retSet.emplace(colInfo.getName());
1483 std::set<std::string> TableView::getColumnStorageNames(
void)
const
1485 std::set<std::string> retSet;
1486 for(
auto& colInfo : columnsInfo_)
1487 retSet.emplace(colInfo.getStorageName());
1492 std::vector<std::string> TableView::getDefaultRowValues(
void)
const
1494 std::vector<std::string> retVec;
1497 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
1504 if(columnsInfo_[col].isChildLink())
1506 const std::vector<std::string>& theDataChoices =
1507 columnsInfo_[col].getDataChoices();
1510 if(!theDataChoices.size() ||
1511 theDataChoices[0] ==
"arbitraryBool=1")
1512 retVec.push_back(columnsInfo_[col].getDefaultValue());
1516 (theDataChoices.size() && theDataChoices[0] ==
"arbitraryBool=0");
1521 bool foundDefault =
false;
1523 for(
const auto& choice : theDataChoices)
1524 if(skipOne && !hasSkipped)
1529 else if(choice == columnsInfo_[col].getDefaultValue())
1531 foundDefault =
true;
1536 if(!foundDefault && theDataChoices.size() > (skipOne ? 1 : 0))
1537 retVec.push_back(theDataChoices[(skipOne ? 1 : 0)]);
1539 retVec.push_back(columnsInfo_[col].getDefaultValue());
1543 retVec.push_back(columnsInfo_[col].getDefaultValue());
1550 unsigned int TableView::getNumberOfRows(
void)
const {
return theDataView_.size(); }
1553 unsigned int TableView::getNumberOfColumns(
void)
const {
return columnsInfo_.size(); }
1556 const TableView::DataView& TableView::getDataView(
void)
const {
return theDataView_; }
1565 const std::vector<TableViewColumnInfo>& TableView::getColumnsInfo(
void)
const
1567 return columnsInfo_;
1571 std::vector<TableViewColumnInfo>* TableView::getColumnsInfoP(
void)
1573 return &columnsInfo_;
1578 if(column >= columnsInfo_.size())
1580 std::stringstream errMsg;
1581 errMsg << __COUT_HDR_FL__ <<
"\nCan't find column " << column
1582 <<
"\n\n\n\nThe column info is likely missing due to incomplete "
1583 "Configuration View filling.\n\n"
1585 __THROW__(errMsg.str().c_str());
1587 return columnsInfo_[column];
1592 void TableView::setUniqueStorageIdentifier(
const std::string& storageUID)
1594 uniqueStorageIdentifier_ = storageUID;
1598 void TableView::setTableName(
const std::string& name) { tableName_ = name; }
1601 void TableView::setComment(
const std::string& comment) { comment_ = comment; }
1604 void TableView::setURIEncodedComment(
const std::string& uriComment)
1606 comment_ = StringMacros::decodeURIComponent(uriComment);
1610 void TableView::setAuthor(
const std::string& author) { author_ = author; }
1613 void TableView::setCreationTime(time_t t) { creationTime_ = t; }
1616 void TableView::setLastAccessTime(time_t t) { lastAccessTime_ = t; }
1619 void TableView::setLooseColumnMatching(
bool setValue)
1621 fillWithLooseColumnMatching_ = setValue;
1625 void TableView::reset(
void)
1630 columnsInfo_.clear();
1631 theDataView_.clear();
1635 void TableView::print(std::ostream& out)
const
1637 out <<
"============================================================================="
1640 out <<
"Print: " << tableName_ <<
" Version: " << version_ <<
" Comment: " << comment_
1641 <<
" Author: " << author_ <<
" Creation Time: " << ctime(&creationTime_) << __E__;
1642 out <<
"\t\tNumber of Cols " << getNumberOfColumns() << __E__;
1643 out <<
"\t\tNumber of Rows " << getNumberOfRows() << __E__;
1645 out <<
"Columns:\t";
1646 for(
int i = 0; i < (int)columnsInfo_.size(); ++i)
1647 out << i <<
":" << columnsInfo_[i].getName() <<
":"
1648 << columnsInfo_[i].getStorageName() <<
":" << columnsInfo_[i].getType() <<
":"
1649 << columnsInfo_[i].getDataType() <<
"\t ";
1652 out <<
"Rows:" << __E__;
1655 for(
int r = 0; r < (int)getNumberOfRows(); ++r)
1657 out << (int)r <<
":\t";
1658 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
1660 out << (int)c <<
":";
1663 if(columnsInfo_[c].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
1665 int choiceIndex = -1;
1666 std::vector<std::string> choices = columnsInfo_[c].getDataChoices();
1667 val = StringMacros::convertEnvironmentVariables(theDataView_[r][c]);
1669 if(val == columnsInfo_[c].getDefaultValue())
1673 for(
int i = 0; i < (int)choices.size(); ++i)
1674 if(val == choices[i])
1675 choiceIndex = i + 1;
1678 out <<
"ChoiceIndex=" << choiceIndex <<
":";
1681 out << theDataView_[r][c];
1701 void TableView::printJSON(std::ostream& out)
const
1704 out <<
"\"NAME\" : \"" << tableName_ <<
"\",\n";
1708 out <<
"\"COMMENT\" : ";
1714 for(
unsigned int i = 0; i < val.size(); ++i)
1718 else if(val[i] ==
'\t')
1720 else if(val[i] ==
'\r')
1725 if(val[i] ==
'"' || val[i] ==
'\\')
1732 out <<
"\"AUTHOR\" : \"" << author_ <<
"\",\n";
1733 out <<
"\"CREATION_TIME\" : " << creationTime_ <<
",\n";
1738 out <<
"\"COL_TYPES\" : {\n";
1739 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
1741 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1742 out <<
"\"" << columnsInfo_[c].getDataType() <<
"\"";
1743 if(c + 1 < (
int)getNumberOfColumns())
1749 out <<
"\"DATA_SET\" : [\n";
1751 for(
int r = 0; r < (int)getNumberOfRows(); ++r)
1754 for(
int c = 0; c < (int)getNumberOfColumns(); ++c)
1756 out <<
"\t\t\"" << columnsInfo_[c].getStorageName() <<
"\" : ";
1758 out <<
"\"" << getEscapedValueAsString(r, c,
false)
1761 if(c + 1 < (
int)getNumberOfColumns())
1766 if(r + 1 < (
int)getNumberOfRows())
1778 std::string restoreJSONStringEntities(
const std::string& str)
1780 unsigned int sz = str.size();
1784 std::stringstream retStr;
1786 for(; i < sz - 1; ++i)
1818 retStr << str[sz - 1];
1820 return retStr.str();
1831 int TableView::fillFromJSON(
const std::string& json)
1833 std::vector<std::string> keys;
1834 keys.push_back(
"NAME");
1835 keys.push_back(
"COMMENT");
1836 keys.push_back(
"AUTHOR");
1837 keys.push_back(
"CREATION_TIME");
1839 keys.push_back(
"DATA_SET");
1843 CV_JSON_FILL_COMMENT,
1844 CV_JSON_FILL_AUTHOR,
1845 CV_JSON_FILL_CREATION_TIME,
1847 CV_JSON_FILL_DATA_SET
1852 sourceColumnMismatchCount_ = 0;
1853 sourceColumnMissingCount_ = 0;
1854 sourceColumnNames_.clear();
1855 unsigned int colFoundCount = 0;
1857 unsigned int row = -1;
1858 unsigned int colSpeedup = 0;
1859 unsigned int startString, startNumber, endNumber = -1;
1860 unsigned int bracketCount = 0;
1861 unsigned int sqBracketCount = 0;
1865 bool isDataArray = 0;
1866 bool keyIsMatch, keyIsComment;
1867 unsigned int keyIsMatchIndex, keyIsMatchStorageIndex, keyIsMatchCommentIndex;
1868 const std::string COMMENT_ALT_KEY =
"COMMENT";
1870 std::string extractedString =
"", currKey =
"", currVal =
"";
1871 unsigned int currDepth;
1873 std::vector<std::string> jsonPath;
1874 std::vector<char> jsonPathType;
1875 char lastPopType =
'_';
1877 unsigned int matchedKey = -1;
1878 unsigned int lastCol = -1;
1881 for(; i < json.size(); ++i)
1886 if(i - 1 < json.size() &&
1887 json[i - 1] ==
'\\')
1890 inQuotes = !inQuotes;
1895 extractedString = restoreJSONStringEntities(
1896 json.substr(startString + 1, i - startString - 1));
1905 if(jsonPathType[jsonPathType.size() - 1] !=
'{' ||
1908 __COUT__ <<
"Invalid ':' position" << __E__;
1913 jsonPathType.push_back(
'K');
1914 jsonPath.push_back(extractedString);
1933 if(lastPopType ==
'{')
1936 if(jsonPathType[jsonPathType.size() - 1] ==
'K')
1939 jsonPath.pop_back();
1940 jsonPathType.pop_back();
1946 currVal = extractedString;
1949 if(endNumber == (
unsigned int)-1 ||
1950 endNumber <= startNumber)
1953 if(endNumber <= startNumber)
1956 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
1959 currDepth = bracketCount;
1961 if(jsonPathType[jsonPathType.size() - 1] ==
'K')
1963 currKey = jsonPath[jsonPathType.size() - 1];
1968 jsonPath.pop_back();
1969 jsonPathType.pop_back();
1971 else if(jsonPathType[jsonPathType.size() - 1] ==
1975 for(
unsigned int k = jsonPathType.size() - 2; k < jsonPathType.size();
1977 if(jsonPathType[k] ==
'K')
1979 currKey = jsonPath[k];
1984 __COUT__ <<
"Invalid array position" << __E__;
1993 __COUT__ <<
"Invalid ',' position" << __E__;
2004 jsonPathType.push_back(
'{');
2005 jsonPath.push_back(
"{");
2018 if(lastPopType !=
'{' &&
2019 jsonPathType[jsonPathType.size() - 1] ==
'K')
2021 currDepth = bracketCount;
2022 currKey = jsonPath[jsonPathType.size() - 1];
2024 currVal = extractedString;
2027 if(endNumber == (
unsigned int)-1 ||
2028 endNumber <= startNumber)
2031 if(endNumber <= startNumber)
2035 json.substr(startNumber + 1, endNumber - startNumber - 1);
2039 jsonPath.pop_back();
2040 jsonPathType.pop_back();
2043 if(jsonPathType[jsonPathType.size() - 1] !=
'{')
2045 __COUT__ <<
"Invalid '}' position" << __E__;
2049 jsonPath.pop_back();
2050 jsonPathType.pop_back();
2056 jsonPathType.push_back(
'[');
2057 jsonPath.push_back(
"[");
2066 if(jsonPathType[jsonPathType.size() - 1] !=
'[')
2068 __COUT__ <<
"Invalid ']' position" << __E__;
2072 currDepth = bracketCount;
2076 currVal = extractedString;
2079 if(endNumber == (
unsigned int)-1 ||
2080 endNumber <= startNumber)
2083 if(endNumber <= startNumber)
2086 currVal = json.substr(startNumber + 1, endNumber - startNumber - 1);
2091 for(
unsigned int k = jsonPathType.size() - 2; k < jsonPathType.size(); --k)
2092 if(jsonPathType[k] ==
'K')
2094 currKey = jsonPath[k];
2099 __COUT__ <<
"Invalid array position" << __E__;
2104 if(jsonPathType[jsonPathType.size() - 1] !=
'[')
2106 __COUT__ <<
"Invalid ']' position" << __E__;
2110 jsonPath.pop_back();
2111 jsonPathType.pop_back();
2120 if(startNumber != (
unsigned int)-1 && endNumber == (
unsigned int)-1)
2129 std::cout << i <<
":\t" << json[i] <<
" - ";
2131 std::cout <<
"ExtKey=";
2132 for(
unsigned int k = 0; k < jsonPath.size(); ++k)
2133 std::cout << jsonPath[k] <<
"/";
2135 std::cout << lastPopType <<
" ";
2136 std::cout << bracketCount <<
" ";
2137 std::cout << sqBracketCount <<
" ";
2138 std::cout << inQuotes <<
" ";
2139 std::cout << newValue <<
"-";
2140 std::cout << currKey <<
"-{" << currDepth <<
"}:";
2141 std::cout << currVal <<
" ";
2142 std::cout << startNumber <<
"-";
2143 std::cout << endNumber <<
" ";
2173 for(
unsigned int k = 0; k < keys.size(); ++k)
2174 if((currDepth == 1 && keys[k] == currKey) ||
2175 (currDepth > 1 && keys[k] == jsonPath[1]))
2178 if(matchedKey != (
unsigned int)-1)
2185 case CV_JSON_FILL_NAME:
2187 setTableName(currVal);
2189 case CV_JSON_FILL_COMMENT:
2191 setComment(currVal);
2193 case CV_JSON_FILL_AUTHOR:
2197 case CV_JSON_FILL_CREATION_TIME:
2199 setCreationTime(strtol(currVal.c_str(), 0, 10));
2204 case CV_JSON_FILL_DATA_SET:
2216 unsigned int col, ccnt = 0;
2217 unsigned int noc = getNumberOfColumns();
2218 for(; ccnt < noc; ++ccnt)
2224 if(fillWithLooseColumnMatching_)
2237 if(getNumberOfRows() == 1)
2238 sourceColumnNames_.emplace(currKey);
2242 if(row >= getNumberOfRows())
2244 __SS__ <<
"Invalid row"
2246 std::cout << ss.str();
2251 theDataView_[row][col] =
2259 col = (ccnt + colSpeedup) % noc;
2265 keyIsComment =
true;
2266 for(keyIsMatchIndex = 0,
2267 keyIsMatchStorageIndex = 0,
2268 keyIsMatchCommentIndex = 0;
2269 keyIsMatchIndex < currKey.size();
2272 if(columnsInfo_[col]
2273 .getStorageName()[keyIsMatchStorageIndex] ==
2275 ++keyIsMatchStorageIndex;
2277 if(currKey[keyIsMatchIndex] ==
'_')
2281 if(keyIsMatchStorageIndex >=
2282 columnsInfo_[col].getStorageName().size() ||
2283 currKey[keyIsMatchIndex] !=
2285 .getStorageName()[keyIsMatchStorageIndex])
2295 keyIsMatchCommentIndex < COMMENT_ALT_KEY.size())
2297 if(currKey[keyIsMatchIndex] !=
2298 COMMENT_ALT_KEY[keyIsMatchCommentIndex])
2301 keyIsComment =
false;
2305 ++keyIsMatchStorageIndex;
2316 if(getNumberOfRows())
2317 sourceColumnMissingCount_ +=
2318 getNumberOfColumns() - colFoundCount;
2326 if(getNumberOfRows() == 1)
2327 sourceColumnNames_.emplace(currKey);
2331 if(row >= getNumberOfRows())
2333 __SS__ <<
"Invalid row"
2335 __COUT__ <<
"\n" << ss.str();
2340 theDataView_[row][col] = currVal;
2350 if(ccnt >= getNumberOfColumns())
2353 <<
"\n\nInvalid column in JSON source data: " << currKey
2354 <<
" not found in column names of table named "
2355 << getTableName() <<
"."
2357 __COUT__ <<
"\n" << ss.str();
2360 ++sourceColumnMismatchCount_;
2361 if(getNumberOfRows() == 1)
2362 sourceColumnNames_.emplace(currKey);
2366 <<
"Ignoring error, and not populating missing column."
2394 bool TableView::isURIEncodedCommentTheSame(
const std::string& comment)
const
2396 std::string compareStr = StringMacros::decodeURIComponent(comment);
2397 return comment_ == compareStr;
2456 int TableView::fillFromCSV(
const std::string& data,
2457 const int& dataOffset,
2458 const std::string& author)
2466 int j = data.find(
',', i);
2467 int k = data.find(
';', i);
2469 bool rowWasModified;
2470 unsigned int countRowsModified = 0;
2471 int authorCol = findColByType(TableViewColumnInfo::TYPE_AUTHOR);
2472 int timestampCol = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
2475 while(k != (
int)(std::string::npos))
2477 rowWasModified =
false;
2478 if(r >= (
int)getNumberOfRows())
2482 rowWasModified =
true;
2485 while(j < k && j != (
int)(std::string::npos))
2490 if(c >= (
int)getNumberOfColumns() - 2)
2493 j = data.find(
',', i);
2498 if(setURIEncodedValue(data.substr(i, j - i), r, c))
2499 rowWasModified =
true;
2502 j = data.find(
',', i);
2507 if(author !=
"" && rowWasModified)
2509 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << __E__;
2510 setValue(author, r, authorCol);
2511 setValue(time(0), r, timestampCol);
2515 ++countRowsModified;
2521 j = data.find(
',', i);
2522 k = data.find(
';', i);
2526 while(r < (
int)getNumberOfRows())
2529 __COUT__ <<
"Row deleted: " << (int)r << __E__;
2530 ++countRowsModified;
2533 __COUT_INFO__ <<
"countRowsModified=" << countRowsModified << __E__;
2535 if(!countRowsModified)
2540 bool match = getColumnStorageNames().size() == getSourceColumnNames().size();
2543 for(
auto& destColName : getColumnStorageNames())
2544 if(getSourceColumnNames().find(destColName) ==
2545 getSourceColumnNames().end())
2547 __COUT__ <<
"Found column name mismach for '" << destColName
2548 <<
"'... So allowing same data!" << __E__;
2557 __SS__ <<
"No rows were modified! No reason to fill a view with same content."
2559 __COUT__ <<
"\n" << ss.str();
2569 sourceColumnNames_.clear();
2570 for(
unsigned int i = 0; i < getNumberOfColumns(); ++i)
2571 sourceColumnNames_.emplace(getColumnsInfo()[i].getStorageName());
2592 bool TableView::setURIEncodedValue(
const std::string& value,
2593 const unsigned int& r,
2594 const unsigned int& c,
2595 const std::string& author)
2597 if(!(c < columnsInfo_.size() && r < getNumberOfRows()))
2599 __SS__ <<
"Invalid row (" << (int)r <<
") col (" << (
int)c << ") requested!"
2600 << "Number of Rows = " << getNumberOfRows()
2601 << "Number of Columns = " << columnsInfo_.size() << __E__;
2606 std::
string valueStr =
StringMacros::decodeURIComponent(value);
2607 std::
string originalValueStr =
2608 getValueAsString(r, c, false);
2616 std::string convertedString = StringMacros::convertEnvironmentVariables(valueStr);
2631 theDataView_[r][c] = valueStr;
2633 else if(columnsInfo_[c].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
2645 setValue(time_t(strtol(valueStr.c_str(), 0, 10)), r, c);
2648 theDataView_[r][c] = valueStr;
2650 bool rowWasModified =
2651 (originalValueStr !=
2652 getValueAsString(r, c,
false));
2655 if(author !=
"" && rowWasModified)
2657 __COUT__ <<
"Row=" << (int)r <<
" was modified!" << __E__;
2658 int authorCol = findColByType(TableViewColumnInfo::TYPE_AUTHOR);
2659 int timestampCol = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
2660 setValue(author, r, authorCol);
2661 setValue(time(0), r, timestampCol);
2664 return rowWasModified;
2668 void TableView::resizeDataView(
unsigned int nRows,
unsigned int nCols)
2672 theDataView_.resize(nRows, std::vector<std::string>(nCols));
2682 unsigned int TableView::addRow(
const std::string& author,
2683 bool incrementUniqueData,
2684 std::string baseNameAutoUID,
2685 unsigned int rowToAdd)
2688 if(rowToAdd == (
unsigned int)-1)
2689 rowToAdd = getNumberOfRows();
2691 theDataView_.resize(getNumberOfRows() + 1,
2692 std::vector<std::string>(getNumberOfColumns()));
2695 for(
unsigned int r = getNumberOfRows() - 2; r >= rowToAdd; --r)
2697 if(r == (
unsigned int)-1)
2699 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
2700 theDataView_[r + 1][col] = theDataView_[r][col];
2703 std::vector<std::string> defaultRowValues = getDefaultRowValues();
2705 char indexString[1000];
2706 std::string tmpString, baseString;
2709 unsigned int maxUniqueData;
2710 std::string numString;
2715 for(
unsigned int col = 0; col < getNumberOfColumns(); ++col)
2722 if(incrementUniqueData &&
2723 (col == getColUID() ||
2724 (getNumberOfRows() > 1 &&
2725 (columnsInfo_[col].getType() == TableViewColumnInfo::TYPE_UNIQUE_DATA ||
2726 columnsInfo_[col].getType() ==
2727 TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA))))
2743 for(
unsigned int r = 0; r < getNumberOfRows(); ++r)
2751 tmpString = theDataView_[r][col];
2755 for(index = tmpString.length() - 1; index < tmpString.length(); --index)
2759 if(!(tmpString[index] >=
'0' && tmpString[index] <=
'9'))
2766 if(tmpString.length() && foundAny)
2769 numString = tmpString.substr(index + 1);
2770 tmpString = tmpString.substr(0, index + 1);
2777 sscanf(numString.c_str(),
"%u", &index);
2779 if(index > maxUniqueData)
2781 maxUniqueData = index;
2782 baseString = tmpString;
2789 sprintf(indexString,
"%u", maxUniqueData);
2793 if(col == getColUID())
2796 if(baseNameAutoUID !=
"")
2797 theDataView_[rowToAdd][col] = baseNameAutoUID + indexString;
2799 theDataView_[rowToAdd][col] = baseString + indexString;
2802 theDataView_[rowToAdd][col] = baseString + indexString;
2804 __COUT__ <<
"New unique data entry is data[" << rowToAdd <<
"][" << col
2805 <<
"] = '" << theDataView_[rowToAdd][col] <<
"'" << __E__;
2810 theDataView_[rowToAdd][col] = defaultRowValues[col];
2815 __COUT__ <<
"Row=" << rowToAdd <<
" was created!" << __E__;
2816 int authorCol = findColByType(TableViewColumnInfo::TYPE_AUTHOR);
2817 int timestampCol = findColByType(TableViewColumnInfo::TYPE_TIMESTAMP);
2818 setValue(author, rowToAdd, authorCol);
2819 setValue(time(0), rowToAdd, timestampCol);
2828 void TableView::deleteRow(
int r)
2830 if(r >= (
int)getNumberOfRows())
2833 __SS__ <<
"Row " << (int)r
2834 <<
" is out of bounds (Row Count = " << getNumberOfRows()
2835 <<
") and can not be deleted." << __E__;
2839 theDataView_.erase(theDataView_.begin() + r);
2858 const bool TableView::getChildLink(
2859 const unsigned int& c,
2861 std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>& linkPair)
const
2863 if(!(c < columnsInfo_.size()))
2865 __SS__ <<
"Invalid col (" << (int)c <<
") requested!" << __E__;
2873 if((isGroup = columnsInfo_[c].isChildLinkGroupID()) ||
2874 columnsInfo_[c].isChildLinkUID())
2878 linkPair.second = c;
2879 std::string index = columnsInfo_[c].getChildLinkIndex();
2884 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
2890 else if(columnsInfo_[col].isChildLink() &&
2891 index == columnsInfo_[col].getChildLinkIndex())
2896 linkPair.first = col;
2902 __SS__ <<
"\tIn view: " << tableName_
2903 <<
", Can't find complete child link for column name "
2904 << columnsInfo_[c].getName() << __E__;
2908 if(!columnsInfo_[c].isChildLink())
2913 std::string index = columnsInfo_[c].getChildLinkIndex();
2918 for(
unsigned int col = 0; col < columnsInfo_.size(); ++col)
2935 if(((columnsInfo_[col].isChildLinkUID() && !(isGroup =
false)) ||
2936 (columnsInfo_[col].isChildLinkGroupID() && (isGroup =
true))) &&
2937 index == columnsInfo_[col].getChildLinkIndex())
2942 linkPair.second = col;
2948 __SS__ <<
"\tIn view: " << tableName_
2949 <<
", Can't find complete child link id for column name "
2950 << columnsInfo_[c].getName() << __E__;