tdaq-develop-2025-02-12
ConfigurationSupervisorBase.cc
1 #include "otsdaq/CoreSupervisors/ConfigurationSupervisorBase.h"
2 #include "otsdaq/TablePlugins/XDAQContextTable/XDAQContextTable.h"
3 
4 using namespace ots;
5 
6 //==============================================================================
9  HttpXmlDocument& xmlOut, ConfigurationManagerRW* cfgMgr, const std::string& username)
10 {
11  std::map<std::string /*type*/, std::pair<std::string /*groupName*/, TableGroupKey>>
12  activeGroupMap = cfgMgr->getActiveTableGroups();
13 
14  for(auto& type : activeGroupMap)
15  {
16  xmlOut.addTextElementToData(type.first + "-ActiveGroupName", type.second.first);
17  xmlOut.addTextElementToData(type.first + "-ActiveGroupKey",
18  type.second.second.toString());
19  //__SUP_COUT__ << "ActiveGroup " << type.first << " " << type.second.first << "("
20  //<< type.second.second << ")" << __E__;
21  }
22  try // try to get matching group alias for active groups
23  {
24  std::map<std::string, TableVersion> activeVersions = cfgMgr->getActiveVersions();
25  std::string groupAliasesTableName =
26  ConfigurationManager::GROUP_ALIASES_TABLE_NAME;
27  if(activeVersions.find(groupAliasesTableName) != activeVersions.end())
28  {
29  // have an active group aliases table at this point
30  std::vector<std::pair<std::string, ConfigurationTree>> aliasNodePairs =
31  cfgMgr->getNode(groupAliasesTableName).getChildren();
32 
33  std::string groupName, groupKey, groupComment, groupType;
34  std::string activeGroupName, activeGroupKey;
35  for(auto& type : activeGroupMap)
36  {
37  activeGroupName = type.second.first;
38  activeGroupKey = type.second.second.toString();
39  for(auto& aliasNodePair : aliasNodePairs)
40  {
41  groupName =
42  aliasNodePair.second.getNode("GroupName").getValueAsString();
43  groupKey =
44  aliasNodePair.second.getNode("GroupKey").getValueAsString();
45  if(groupName == activeGroupName && groupKey == activeGroupKey)
46  { // found match!
47  xmlOut.addTextElementToData(type.first + "-ActiveGroupAlias",
48  aliasNodePair.first);
49  break;
50  }
51  } // end alias match search loop
52  } // end active group loop
53  } // end handling of matching group alias to active groups
54  // else ignore missing active group alias table or active backbone
55  }
56  catch(...)
57  {
58  __COUT__ << "Ignoring failure getting alias for active groups" << __E__;
59  }
60 
61  // always add version tracking bool
62  xmlOut.addTextElementToData(
63  "versionTracking",
64  ConfigurationInterface::isVersionTrackingEnabled() ? "ON" : "OFF");
65 
66  xmlOut.addTextElementToData("configUsername", username);
67 
68 } // end getConfigurationStatusXML()
69 
70 //==============================================================================
79  ConfigurationManagerRW* cfgMgr,
80  const std::string& tableName,
81  TableVersion version,
82  bool makeTemporary,
83  const std::string& data,
84  const int& dataOffset,
85  const std::string& author,
86  const std::string& comment,
87  bool sourceTableAsIs,
88  bool lookForEquivalent)
89 try
90 {
91  //__COUT__ << "handleCreateTableXML: " << tableName << " version: " <<
92  // version
93  // << " dataOffset: " << dataOffset << __E__;
94 
95  //__COUT__ << "data: " << data << __E__;
96 
97  // create temporary version from starting version
98  if(!version.isInvalid()) // if not using mock-up, make sure starting version is
99  // loaded
100  {
101  try
102  {
103  cfgMgr->getVersionedTableByName(tableName, version);
104  }
105  catch(...)
106  {
107  // force to mockup
108  version = TableVersion();
109  }
110  }
111 
112  TableBase* table = cfgMgr->getTableByName(tableName);
113 
114  // check that the source version has the right number of columns
115  // if there is a mismatch, start from mockup
116  if(!version.isInvalid()) // if not using mock-up, then the starting version is the
117  // active one
118  {
119  // compare active to mockup column counts
120  if(table->getViewP()->getDataColumnSize() !=
121  table->getMockupViewP()->getNumberOfColumns() ||
122  table->getViewP()->getSourceColumnMismatch() != 0)
123  {
124  __COUT__ << "table->getViewP()->getNumberOfColumns() "
125  << table->getViewP()->getNumberOfColumns() << __E__;
126  __COUT__ << "table->getMockupViewP()->getNumberOfColumns() "
127  << table->getMockupViewP()->getNumberOfColumns() << __E__;
128  __COUT__ << "table->getViewP()->getSourceColumnMismatch() "
129  << table->getViewP()->getSourceColumnMismatch() << __E__;
130  __COUT_INFO__
131  << "Source view v" << version
132  << " has a mismatch in the number of columns, so using mockup as source."
133  << __E__;
134  version = TableVersion(); // invalid = mockup
135  }
136  }
137 
138  bool ignoreDuplicates = false;
139  if(!version.isTemporaryVersion() && sourceTableAsIs &&
140  table->getViewP()->getSourceColumnNames().size() !=
141  table->getViewP()->getDataColumnSize())
142  {
143  __COUT__ << "table->getViewP()->getNumberOfColumns() "
144  << table->getViewP()->getNumberOfColumns() << __E__;
145  __COUTV__(table->getViewP()->getSourceColumnNames().size());
146  __COUT_INFO__
147  << "Source view v" << version
148  << " has a mismatch in the number of columns, so forcing new version saved."
149  << __E__;
150  ignoreDuplicates = true;
151  }
152 
153  // create a temporary version from the source version
154  TableVersion temporaryVersion = table->createTemporaryView(version);
155 
156  __COUT__ << "\t\ttemporaryVersion: " << temporaryVersion << __E__;
157 
158  TableView* cfgView = table->getTemporaryView(temporaryVersion);
159 
160  int retVal;
161  try
162  {
163  // returns -1 on error that data was unchanged
164  retVal = sourceTableAsIs ? 0 : cfgView->fillFromCSV(data, dataOffset, author);
165 
166  if(retVal == 1) // data was same but columns are different!
167  {
168  __COUT__ << "Data was the same, but columns have changed!" << __E__;
169  __COUTV__(sourceTableAsIs);
170  __COUTV__(lookForEquivalent);
171  }
172 
173  cfgView->setURIEncodedComment(comment);
174  __COUT__ << "Table comment was set to:\n\t" << cfgView->getComment() << __E__;
175  }
176  catch(...) // erase temporary view before re-throwing error
177  {
178  __COUT__ << "Caught error while editing. Erasing temporary version." << __E__;
179  table->eraseView(temporaryVersion);
180  throw;
181  }
182 
183  // Note: be careful with any further table operations at this point..
184  // must catch errors and erase temporary version on failure.
185 
186  // only consider it an error if source version was persistent version
187  // allow it if source version is temporary and we are making a persistent version now
188  // also, allow it if version tracking is off.
189  if(retVal < 0 && (!version.isTemporaryVersion() || makeTemporary) &&
190  ConfigurationInterface::isVersionTrackingEnabled())
191  {
192  if(!version.isInvalid() && // if source version was mockup, then consider it
193  // attempt to create a blank table
194  !version.isScratchVersion()) // if source version was scratch, then consider
195  // it attempt to make it persistent
196  {
197  __SS__ << "No rows were modified! No reason to fill a view with same content."
198  << __E__;
199  __COUT_ERR__ << "\n" << ss.str();
200  // delete temporaryVersion
201  table->eraseView(temporaryVersion);
202  __SS_THROW__;
203  }
204  else if(version.isInvalid())
205  __COUT__ << "This was interpreted as an attempt to create a blank table."
206  << __E__;
207  else if(version.isScratchVersion())
208  __COUT__ << "This was interpreted as an attempt to make a persistent "
209  "version of the scratch table."
210  << __E__;
211  else
212  {
213  __SS__;
214  __THROW__(ss.str() + "impossible!");
215  }
216  }
217  else if(retVal < 0 && (version.isTemporaryVersion() && !makeTemporary))
218  {
219  __COUT__ << "Allowing the static data because this is converting from "
220  "temporary to persistent version."
221  << __E__;
222  }
223  else if(retVal < 0 && !ConfigurationInterface::isVersionTrackingEnabled())
224  {
225  __COUT__ << "Allowing the static data because version tracking is OFF." << __E__;
226  }
227  else if(retVal < 0)
228  {
229  __SS__ << "This should not be possible! Fatal error." << __E__;
230  // delete temporaryVersion
231  table->eraseView(temporaryVersion);
232  __SS_THROW__;
233  }
234 
235  // note: if sourceTableAsIs, accept equivalent versions
237  xmlOut,
238  cfgMgr,
239  tableName,
240  version,
241  makeTemporary,
242  table,
243  temporaryVersion,
244  ignoreDuplicates /*ignoreDuplicates*/,
245  lookForEquivalent || sourceTableAsIs /*lookForEquivalent*/);
246 
247  if(ignoreDuplicates && sourceTableAsIs) // reset cache for this table
248  {
249  table = cfgMgr->getTableByName(tableName);
250  table->eraseView(newVersion);
251  }
252 } // end handleCreateTableXML()
253 catch(std::runtime_error& e)
254 {
255  __SS__ << "Error saving new table!\n\n " << e.what() << __E__;
256  __COUT__ << "\n" << ss.str() << __E__;
257  xmlOut.addTextElementToData("Error", ss.str());
258 }
259 catch(...)
260 {
261  __SS__ << "Error saving new table!" << __E__;
262  try
263  {
264  throw;
265  } //one more try to printout extra info
266  catch(const std::exception& e)
267  {
268  ss << "Exception message: " << e.what();
269  }
270  catch(...)
271  {
272  }
273  __COUT__ << "\n" << ss.str() << __E__;
274  xmlOut.addTextElementToData("Error", ss.str());
275 } // end handleCreateTableXML() catch
276 
277 //==============================================================================
283  HttpXmlDocument& xmlOut,
284  ConfigurationManagerRW* cfgMgr,
285  const std::string& tableName,
286  TableVersion originalVersion,
287  bool makeTemporary,
288  TableBase* table,
289  TableVersion temporaryModifiedVersion,
290  bool ignoreDuplicates,
291  bool lookForEquivalent)
292 {
293  bool foundEquivalent;
294  TableVersion newAssignedVersion =
295  cfgMgr->saveModifiedVersion(tableName,
296  originalVersion,
297  makeTemporary,
298  table,
299  temporaryModifiedVersion,
300  ignoreDuplicates,
301  lookForEquivalent,
302  &foundEquivalent);
303 
304  xmlOut.addTextElementToData("savedName", tableName);
305  xmlOut.addTextElementToData("savedVersion", newAssignedVersion.toString());
306 
307  if(foundEquivalent)
308  {
309  xmlOut.addTextElementToData("foundEquivalentVersion", "1");
310  xmlOut.addTextElementToData(tableName + "_foundEquivalentVersion", "1");
311  }
312  return newAssignedVersion;
313 } // end saveModifiedVersionXML()
314 
315 //==============================================================================
335  HttpXmlDocument& xmlOut,
336  ConfigurationManagerRW* cfgMgr,
337  const std::string& groupName,
338  const std::string& tableList,
339  bool allowDuplicates,
340  bool ignoreWarnings,
341  const std::string& groupComment,
342  bool lookForEquivalent)
343 try
344 {
345  __COUTT__ << "handleCreateTableGroupXML start runtime=" << cfgMgr->runTimeSeconds()
346  << __E__;
347 
348  xmlOut.addTextElementToData("AttemptedNewGroupName", groupName);
349 
350  // make sure not using partial tables or anything weird when creating the group
351  // so start from scratch and load backbone, but allow errors
352  std::string accumulatedWarnings;
353  const std::map<std::string, TableInfo>& allTableInfo =
354  cfgMgr->getAllTableInfo(true /* refresh */,
355  &accumulatedWarnings,
356  "" /* errorFilterName */,
357  true /* getGroupKeys*/,
358  false /* getGroupInfo */,
359  true /* initializeActiveGroups */);
360  __COUT_WARN__ << "Ignoring these errors: " << accumulatedWarnings << __E__;
361  // cfgMgr->loadConfigurationBackbone(); //already loaded by initializeActiveGroups of getAllTableInfo
362 
363  __COUTT__ << "handleCreateTableGroupXML loaded runtime=" << cfgMgr->runTimeSeconds()
364  << __E__;
365 
366  std::map<std::string /*tableName*/,
367  std::map<std::string /*aliasName*/, TableVersion /*version*/>>
368  versionAliases = cfgMgr->getVersionAliases();
369  // for(const auto& aliases : versionAliases)
370  // for(const auto& alias : aliases.second)
371  // __COUT__ << aliases.first << " " << alias.first << " " << alias.second
372  // << __E__;
373 
374  std::map<std::string /*name*/, TableVersion /*version*/> groupMembers;
375  std::map<std::string /*name*/, std::string /*alias*/> memberTableAliases;
376 
377  std::string name, versionStr, alias;
378  TableVersion version;
379  auto c = tableList.find(',', 0);
380  auto i = c;
381  i = 0; // auto used to get proper index/length type
382  while(c < tableList.length())
383  {
384  // add the table and version pair to the map
385  name = tableList.substr(i, c - i);
386  i = c + 1;
387  c = tableList.find(',', i);
388  if(c == std::string::npos) // missing version list entry?!
389  {
390  __SS__ << "Incomplete Table Name-Version pair!" << __E__;
391  __COUT_ERR__ << "\n" << ss.str();
392  xmlOut.addTextElementToData("Error", ss.str());
393  return;
394  }
395 
396  versionStr = tableList.substr(i, c - i);
397  i = c + 1;
398  c = tableList.find(',', i);
399 
400  //__COUT__ << "name: " << name << __E__;
401  //__COUT__ << "versionStr: " << versionStr << __E__;
402 
403  // check if version is an alias and convert
404  if(versionStr.find(ConfigurationManager::ALIAS_VERSION_PREAMBLE) == 0)
405  {
406  alias =
407  versionStr.substr(ConfigurationManager::ALIAS_VERSION_PREAMBLE.size());
408 
409  __COUT__ << "Found alias " << name << " " << versionStr << __E__;
410 
411  // convert alias to version
412  if(versionAliases.find(name) != versionAliases.end() &&
413  versionAliases[name].find(alias) != versionAliases[name].end())
414  {
415  version = versionAliases[name][alias];
416  __COUT__ << name << " version alias '" << alias
417  << "'translated to: " << version << __E__;
418 
419  memberTableAliases[name] = alias;
420  }
421  else
422  {
423  __SS__ << "version alias '"
424  << versionStr.substr(
425  ConfigurationManager::ALIAS_VERSION_PREAMBLE.size())
426  << "' was not found in active version aliases!" << __E__;
427  __COUT_ERR__ << "\n" << ss.str();
428  xmlOut.addTextElementToData("Error", ss.str());
429  return;
430  }
431  }
432  else
433  version = TableVersion(versionStr);
434 
435  if(version.isTemporaryVersion())
436  {
437  __SS__ << "Groups can not be created using temporary member tables. "
438  << "Table member '" << name << "' with temporary version '" << version
439  << "' is illegal." << __E__;
440  xmlOut.addTextElementToData("Error", ss.str());
441  return;
442  }
443 
444  // enforce that table exists
445  if(allTableInfo.find(name) == allTableInfo.end())
446  {
447  __SS__ << "Groups can not be created using mock-up member tables of "
448  "undefined tables. "
449  << "Table member '" << name << "' is not defined." << __E__;
450  xmlOut.addTextElementToData("Error", ss.str());
451  return;
452  }
453 
454  if(version.isMockupVersion())
455  {
456  // if mockup, then generate a new persistent version to use based on mockup
457  TableBase* table = cfgMgr->getTableByName(name);
458  // create a temporary version from the mockup as source version
459  TableVersion temporaryVersion = table->createTemporaryView();
460  __COUT__ << "\t\ttemporaryVersion: " << temporaryVersion << __E__;
461 
462  // if other versions exist check for another mockup, and use that instead
463  __COUT__ << "Creating version from mock-up for name: " << name
464  << " inputVersionStr: " << versionStr << __E__;
465 
466  // set table comment
467  table->getTemporaryView(temporaryVersion)
468  ->setComment("Auto-generated from mock-up.");
469 
470  // finish off the version creation
472  xmlOut,
473  cfgMgr,
474  name,
475  TableVersion() /*original source is mockup*/,
476  false /* makeTemporary */,
477  table,
478  temporaryVersion /*temporary modified version*/,
479  false /*ignore duplicates*/,
480  true /*look for equivalent*/);
481 
482  __COUT__ << "Using mockup version: " << version << __E__;
483  }
484 
485  //__COUT__ << "version: " << version << __E__;
486  groupMembers[name] = version;
487  } // end member verification loop
488 
489  __COUTT__ << "handleCreateTableGroupXML tables saved runtime="
490  << cfgMgr->runTimeSeconds() << __E__;
491 
492  __COUTV__(StringMacros::mapToString(memberTableAliases));
493 
494  if(!allowDuplicates)
495  {
496  __COUT__ << "Checking for duplicate groups..." << __E__;
497  try
498  {
499  TableGroupKey foundKey =
500  cfgMgr->findTableGroup(groupName, groupMembers, memberTableAliases);
501  __COUTT__ << "handleCreateTableGroupXML group duplicates checked runtime="
502  << cfgMgr->runTimeSeconds() << __E__;
503  if(!foundKey.isInvalid())
504  {
505  // return found equivalent key
506  xmlOut.addTextElementToData("TableGroupName", groupName);
507  xmlOut.addTextElementToData("TableGroupKey", foundKey.toString());
508 
509  if(lookForEquivalent)
510  {
511  __COUT__ << "Found equivalent group key (" << foundKey << ") for "
512  << groupName << "." << __E__;
513  // allow this equivalent group to be the response without an error
514  xmlOut.addTextElementToData("foundEquivalentKey", "1"); // indicator
515 
516  // insert get table info
518  xmlOut, cfgMgr, groupName, foundKey, ignoreWarnings);
519  return;
520  }
521  else // treat as error, if not looking for equivalent
522  {
523  __COUT__ << "Treating duplicate group as error." << __E__;
524  __SS__ << ("Failed to create table group: " + groupName +
525  ". It is a duplicate of an existing group key (" +
526  foundKey.toString() + ")");
527  __COUT_ERR__ << ss.str() << __E__;
528  xmlOut.addTextElementToData("Error", ss.str());
529  return;
530  }
531  }
532 
533  __COUT__ << "Check for duplicate groups complete." << __E__;
534  }
535  catch(...)
536  {
537  __COUT_WARN__ << "Ignoring errors looking for duplicate groups! Proceeding "
538  "with new group creation."
539  << __E__;
540  }
541  }
542 
543  // check the group for errors before creating group
544  try
545  {
546  cfgMgr->loadMemberMap(groupMembers);
547 
548  std::string accumulateErrors = "";
549  for(auto& groupMemberPair : groupMembers)
550  {
551  TableView* cfgViewPtr =
552  cfgMgr->getTableByName(groupMemberPair.first)->getViewP();
553  if(cfgViewPtr->getDataColumnSize() != cfgViewPtr->getNumberOfColumns() ||
554  cfgViewPtr->getSourceColumnMismatch() !=
555  0) // check for column size mismatch
556  {
557  // const std::set<std::string> srcColNames = cfgViewPtr->getSourceColumnNames();
558  __SS__ << "\n\nThere were errors found in loading a member table "
559  << groupMemberPair.first << ":v" << cfgViewPtr->getVersion()
560  << ". Please see the details below:\n\n"
561  << cfgViewPtr->getMismatchColumnInfo();
562 
563  __COUT_ERR__ << "\n" << ss.str();
564  xmlOut.addTextElementToData("Error", ss.str());
565  return;
566  }
567  }
568  }
569  catch(std::runtime_error& e)
570  {
571  __SS__ << "Failed to create table group: " << groupName
572  << ".\nThere were problems loading the chosen members:\n\n"
573  << e.what() << __E__;
574  __COUT_ERR__ << "\n" << ss.str();
575  xmlOut.addTextElementToData("Error", ss.str());
576  return;
577  }
578  catch(...)
579  {
580  __SS__ << "Failed to create table group: " << groupName << __E__;
581  try
582  {
583  throw;
584  } //one more try to printout extra info
585  catch(const std::exception& e)
586  {
587  ss << "Exception message: " << e.what();
588  }
589  catch(...)
590  {
591  }
592  __COUT_ERR__ << "\n" << ss.str();
593  xmlOut.addTextElementToData("Error", ss.str());
594  return;
595  }
596 
597  __COUTT__ << "handleCreateTableGroupXML group members init checked runtime="
598  << cfgMgr->runTimeSeconds() << __E__;
599 
600  // check the tree for warnings before creating group
601  std::string accumulateTreeErrs;
602  cfgMgr->getChildren(&groupMembers, &accumulateTreeErrs);
603  if(accumulateTreeErrs != "")
604  {
605  __COUT_WARN__ << "\n" << accumulateTreeErrs << __E__;
606  if(!ignoreWarnings)
607  {
608  xmlOut.addTextElementToData("TreeErrors", accumulateTreeErrs);
609  return;
610  }
611  }
612 
613  __COUTT__ << "handleCreateTableGroupXML tree checked runtime="
614  << cfgMgr->runTimeSeconds() << __E__;
615 
616  TableGroupKey newKey;
617  try
618  {
619  __COUT__ << "Saving new group..." << __E__;
620  newKey = cfgMgr->saveNewTableGroup(
621  groupName, groupMembers, groupComment, &memberTableAliases);
622  }
623  catch(std::runtime_error& e)
624  {
625  __SS__ << "Failed to create table group: " << groupName << __E__;
626  ss << "\n\n" << e.what() << __E__;
627  __COUT_ERR__ << ss.str();
628  xmlOut.addTextElementToData("Error", ss.str());
629  return;
630  }
631  catch(...)
632  {
633  __SS__ << "Failed to create table group: " << groupName << __E__;
634  try
635  {
636  throw;
637  } //one more try to printout extra info
638  catch(const std::exception& e)
639  {
640  ss << "Exception message: " << e.what();
641  }
642  catch(...)
643  {
644  }
645  __COUT_ERR__ << ss.str();
646  xmlOut.addTextElementToData("Error", ss.str());
647  return;
648  }
649 
650  __COUTT__ << "handleCreateTableGroupXML group saved runtime="
651  << cfgMgr->runTimeSeconds() << __E__;
652 
653  // insert get table info
654  __COUT__ << "Loading new table group..." << __E__;
655  handleGetTableGroupXML(xmlOut, cfgMgr, groupName, newKey, ignoreWarnings);
656 
657  __COUTT__ << "handleCreateTableGroupXML end runtime=" << cfgMgr->runTimeSeconds()
658  << __E__;
659 
660 } // end handleCreateTableGroupXML()
661 catch(std::runtime_error& e)
662 {
663  __SS__ << "Error saving table group!\n\n " << e.what() << __E__;
664  __COUT_ERR__ << "\n" << ss.str() << __E__;
665  xmlOut.addTextElementToData("Error", ss.str());
666 }
667 catch(...)
668 {
669  __SS__ << "Error saving table group!" << __E__;
670  try
671  {
672  throw;
673  } //one more try to printout extra info
674  catch(const std::exception& e)
675  {
676  ss << "Exception message: " << e.what();
677  }
678  catch(...)
679  {
680  }
681  __COUT_ERR__ << "\n" << ss.str() << __E__;
682  xmlOut.addTextElementToData("Error", ss.str());
683 } // end handleCreateTableGroupXML() catch
684 
685 //==============================================================================
709  ConfigurationManagerRW* cfgMgr,
710  const std::string& groupName,
711  TableGroupKey groupKey,
712  bool ignoreWarnings)
713 try
714 {
715  // char tmpIntStr[100];
716  xercesc::DOMElement *parentEl, *configEl;
717 
718  // steps:
719  // if invalid key, get latest key
720  // get specific group with key
721  // give member names and versions
722  // get all table groups to locate historical keys
723  // get all groups to find historical keys
724 
725  // std::set<std::string /*name+version*/> allGroups =
726  // cfgMgr->getConfigurationInterface()->getAllTableGroupNames(groupName);
727  // std::string name;
728  // TableGroupKey key;
729  // //put them in a set to sort them as TableGroupKey defines for operator<
730  // std::set<TableGroupKey> sortedKeys;
731  // for(auto& group: allGroups)
732  // {
733  // //now uses database filter
734  // TableGroupKey::getGroupNameAndKey(group,name,key);
735  // //if(name == groupName)
736  // sortedKeys.emplace(key);
737  // }
738 
739  {
740  const GroupInfo& groupInfo = cfgMgr->getGroupInfo(groupName);
741  const std::set<TableGroupKey>& sortedKeys = groupInfo.keys_; // rename
742 
743  __COUTT__ << groupName << " keys: " << StringMacros::setToString(groupInfo.keys_)
744  << __E__;
745  __COUTT__ << "Active groups: "
746  << StringMacros::mapToString(cfgMgr->getActiveTableGroups()) << __E__;
747  __COUTT__ << "Active tables: "
748  << StringMacros::mapToString(cfgMgr->getActiveVersions()) << __E__;
749 
750  if(groupKey.isInvalid() || // if invalid or not found, get latest
751  sortedKeys.find(groupKey) == sortedKeys.end())
752  {
753  // report error if group key not found
754  if(!groupKey.isInvalid() || sortedKeys.size() == 0)
755  {
756  // attempt to reload all group info and power through
757  std::string accumulatedWarnings;
758  __COUTT__ << "Attempting full table refresh (assuming cache not yet "
759  "established)."
760  << __E__;
761  /*const std::map<std::string, TableInfo>& allTableInfo = */ cfgMgr
762  ->getAllTableInfo(true /* refresh */,
763  &accumulatedWarnings,
764  "" /* errorFilterName */,
765  true /* getGroupKeys*/,
766  false /* getGroupInfo */,
767  true /* initializeActiveGroups */);
768  __COUTT__ << "After full table refresh (assuming cache not yet "
769  "established) so ignoring these errors: "
770  << accumulatedWarnings << __E__;
771 
772  // xmlOut.addTextElementToData("Error", ss.str());
773 
774  const GroupInfo& groupInfo2 = cfgMgr->getGroupInfo(groupName);
775  const std::set<TableGroupKey>& sortedKeys2 = groupInfo2.keys_; // rename
776 
777  if(sortedKeys2.find(groupKey) == sortedKeys2.end())
778  {
779  __SS__ << "Group key " << groupKey << " was not found for group '"
780  << groupName << "!'" << __E__;
781  ss << "Her are the found " << sortedKeys2.size() << " '" << groupName
782  << "' keys: " << __E__;
783  for(auto& keyInOrder : sortedKeys2)
784  ss << "\t" << keyInOrder << __E__;
785  __COUT_WARN__ << "\n" << ss.str() << __E__;
786  }
787 
788  for(auto& keyInOrder : sortedKeys2)
789  xmlOut.addTextElementToData("HistoricalTableGroupKey",
790  keyInOrder.toString());
791  }
792  else
793  {
794  if(sortedKeys.size())
795  groupKey = *sortedKeys.rbegin();
796  __COUT_WARN__
797  << "Group key requested was invalid or not found, going with latest "
798  << groupKey << __E__;
799 
800  // add all other sorted keys for this groupName
801  for(auto& keyInOrder : sortedKeys)
802  xmlOut.addTextElementToData("HistoricalTableGroupKey",
803  keyInOrder.toString());
804  }
805  }
806  else
807  {
808  // add all other sorted keys for this groupName
809  for(auto& keyInOrder : sortedKeys)
810  xmlOut.addTextElementToData("HistoricalTableGroupKey",
811  keyInOrder.toString());
812  }
813 
814  if(cfgMgr->getActiveVersions().size() == 0)
815  {
816  __COUTT__
817  << "There are no active tables. Attempting to initialize active groups."
818  << __E__;
819  //if no active tables, attempt to init active groups (it should prevent confusing warnings to users complaining about a partially loaded configuration)
820  std::string tmpAccumulateWarnings;
821  cfgMgr->init(0 /*accumulatedErrors*/,
822  false /*initForWriteAccess*/,
823  &tmpAccumulateWarnings);
824  __COUTT__ << "Now Active tables: "
825  << StringMacros::mapToString(cfgMgr->getActiveVersions()) << __E__;
826  __COUTT__ << "Ingoring warnings during init of active groups: "
827  << tmpAccumulateWarnings << __E__;
828  }
829  }
830 
831  xmlOut.addTextElementToData("TableGroupName", groupName);
832  xmlOut.addTextElementToData("TableGroupKey", groupKey.toString());
833 
834  parentEl = xmlOut.addTextElementToData("TableGroupMembers", "");
835 
836  // get specific group with key
837  std::map<std::string /*name*/, TableVersion /*version*/> memberMap;
838  std::map<std::string /*name*/, std::string /*alias*/> groupMemberAliases;
839 
840  __COUT__ << "groupName=" << groupName << __E__;
841  __COUT__ << "groupKey=" << groupKey << __E__;
842 
843  const std::map<std::string, TableInfo>& allTableInfo = cfgMgr->getAllTableInfo();
844  std::map<std::string, TableInfo>::const_iterator it;
845 
846  // load group so comments can be had
847  // and also group metadata (author, comment, createTime)
848  try
849  {
850  std::string groupAuthor, groupComment, groupCreationTime, groupTypeString;
851  std::string accumulateTreeErrors;
852 
853  __COUTV__(ignoreWarnings);
854  cfgMgr->loadTableGroup(groupName,
855  groupKey,
856  false /*doActivate*/,
857  &memberMap,
858  0 /*progressBar*/,
859  ignoreWarnings ? 0 : /*accumulateTreeErrors*/
860  &accumulateTreeErrors,
861  &groupComment,
862  &groupAuthor,
863  &groupCreationTime,
864  false /*doNotLoadMember*/,
865  &groupTypeString,
866  &groupMemberAliases);
867 
868  if(accumulateTreeErrors != "")
869  {
870  __COUTV__(accumulateTreeErrors);
871  xmlOut.addTextElementToData("TreeErrors", accumulateTreeErrors);
872  }
873 
874  xmlOut.addTextElementToData("TableGroupAuthor", groupAuthor);
875  xmlOut.addTextElementToData("TableGroupComment", groupComment);
876  xmlOut.addTextElementToData("TableGroupCreationTime", groupCreationTime);
877  xmlOut.addTextElementToData("TableGroupType", groupTypeString);
878  }
879  catch(const std::runtime_error& e)
880  {
881  __SS__ << "Table group \"" + groupName + "(" + groupKey.toString() + ")" +
882  "\" members can not be loaded!\n\n" + e.what()
883  << __E__;
884  __COUT_ERR__ << ss.str();
885  xmlOut.addTextElementToData("Error", ss.str());
886  // return;
887  }
888  catch(...)
889  {
890  __SS__ << "Table group \"" + groupName + "(" + groupKey.toString() + ")" +
891  "\" members can not be loaded!"
892  << __E__;
893  try
894  {
895  throw;
896  } //one more try to printout extra info
897  catch(const std::exception& e)
898  {
899  ss << "Exception message: " << e.what();
900  }
901  catch(...)
902  {
903  }
904  __COUT_ERR__ << ss.str();
905  xmlOut.addTextElementToData("Error", ss.str());
906  // return;
907  }
908 
909  __COUTV__(StringMacros::mapToString(groupMemberAliases));
910 
911  std::map<std::string, std::map<std::string, TableVersion>> versionAliases =
912  cfgMgr->getVersionAliases();
913 
914  __COUT__ << "# of table version aliases: " << versionAliases.size() << __E__;
915 
916  // Seperate loop to get name and version
917  for(auto& memberPair : memberMap)
918  {
919  xmlOut.addTextElementToParent("MemberName", memberPair.first, parentEl);
920 
921  // if member is in groupMemberAliases, then alias version
922  if(groupMemberAliases.find(memberPair.first) != groupMemberAliases.end())
923  configEl = xmlOut.addTextElementToParent(
924  "MemberVersion",
925  ConfigurationManager::ALIAS_VERSION_PREAMBLE +
926  groupMemberAliases[memberPair.first], // return the ALIAS:<alias>
927  parentEl);
928  else
929  configEl = xmlOut.addTextElementToParent(
930  "MemberVersion", memberPair.second.toString(), parentEl);
931 
932  it = allTableInfo.find(memberPair.first);
933  if(it == allTableInfo.end())
934  {
935  xmlOut.addTextElementToData(
936  "Error", "Table \"" + memberPair.first + "\" can not be retrieved!");
937  continue;
938  }
939 
940  if(versionAliases.find(it->first) != versionAliases.end())
941  for(auto& aliasVersion : versionAliases[it->first])
942  xmlOut.addTextElementToParent(
943  "TableExistingVersion",
944  ConfigurationManager::ALIAS_VERSION_PREAMBLE + aliasVersion.first,
945  configEl);
946 
947  for(auto& version : it->second.versions_)
948  // if(version == memberPair.second) continue; //CHANGED by RAR on 11/14/2016
949  // (might as well show all versions in list to avoid user confusion) else
950  xmlOut.addTextElementToParent(
951  "TableExistingVersion", version.toString(), configEl);
952  }
953  // Seperate loop just for getting the Member Comment
954  for(auto& memberPair : memberMap)
955  {
956  //__COUT__ << "\tMember table " << memberPair.first << ":" <<
957  // memberPair.second << __E__;
958 
959  // xmlOut.addTextElementToParent("MemberName", memberPair.first, parentEl);
960  // if(commentsLoaded)
961  xmlOut.addTextElementToParent(
962  "MemberComment",
963  allTableInfo.at(memberPair.first).tablePtr_->getView().getComment(),
964  parentEl);
965  // else
966  // xmlOut.addTextElementToParent("MemberComment", "", parentEl);
967 
968  // __COUT__ << "\tMember table " << memberPair.first << ":" <<
969  // memberPair.second << __E__;
970 
971  // configEl = xmlOut.addTextElementToParent("MemberVersion",
972  // memberPair.second.toString(), parentEl);
973 
974  /* it = allTableInfo.find(memberPair.first);
975  if(it == allTableInfo.end())
976  {
977  xmlOut.addTextElementToData("Error","Table \"" +
978  memberPair.first +
979  "\" can not be retrieved!");
980  return;
981  }
982  */
983  // include aliases for this table
984  /*if(versionAliases.find(it->first) != versionAliases.end())
985  for (auto& aliasVersion:versionAliases[it->first])
986  xmlOut.addTextElementToParent("TableExistingVersion",
987  ConfigurationManager::ALIAS_VERSION_PREAMBLE + aliasVersion.first,
988  configEl);
989 
990  for (auto& version:it->second.versions_)
991  //if(version == memberPair.second) continue; //CHANGED by RAR on 11/14/2016
992  (might as well show all versions in list to avoid user confusion)
993  //else
994  xmlOut.addTextElementToParent("TableExistingVersion",
995  version.toString(), configEl);
996  */
997  }
998 
999 } // end handleGetTableGroupXML()
1000 catch(std::runtime_error& e)
1001 {
1002  __SS__ << ("Error getting table group!\n\n" + std::string(e.what())) << __E__;
1003  __COUT_ERR__ << "\n" << ss.str();
1004  xmlOut.addTextElementToData("Error", ss.str());
1005 }
1006 catch(...)
1007 {
1008  __SS__ << ("Error getting table group!\n\n") << __E__;
1009  try
1010  {
1011  throw;
1012  } //one more try to printout extra info
1013  catch(const std::exception& e)
1014  {
1015  ss << "Exception message: " << e.what();
1016  }
1017  catch(...)
1018  {
1019  }
1020  __COUT_ERR__ << "\n" << ss.str();
1021  xmlOut.addTextElementToData("Error", ss.str());
1022 } // end handleGetTableGroupXML() catch
1023 
1024 //==============================================================================
1025 bool ConfigurationSupervisorBase::handleAddDesktopIconXML(
1026  HttpXmlDocument& xmlOut,
1027  ConfigurationManagerRW* cfgMgr,
1028  const std::string& iconCaption,
1029  const std::string& iconAltText,
1030  const std::string& iconFolderPath,
1031  const std::string& iconImageURL,
1032  const std::string& iconWindowURL,
1033  const std::string& iconPermissions,
1034  std::string windowLinkedApp /*= ""*/,
1035  unsigned int windowLinkedAppLID /*= 0*/,
1036  bool enforceOneWindowInstance /*= false*/,
1037  const std::string& windowParameters /*= ""*/)
1038 try
1039 {
1040  cfgMgr->getAllTableInfo(true /* refresh */);
1041 
1042  const std::string& author = cfgMgr->getUsername();
1043 
1044  __COUTV__(author);
1045  __COUTV__(iconCaption);
1046  __COUTV__(iconAltText);
1047  __COUTV__(iconFolderPath);
1048  __COUTV__(iconImageURL);
1049  __COUTV__(iconWindowURL);
1050  __COUTV__(iconPermissions);
1051  __COUTV__(windowLinkedApp);
1052  __COUTV__(windowLinkedAppLID);
1053  __COUTV__(enforceOneWindowInstance);
1054 
1055  __COUTV__(windowParameters); // map: CSV list
1056 
1057  // steps:
1058  // activate active context
1059  // modify desktop table and desktop parameters table
1060  // save, activate, and modify alias
1061  // just to match syntax in ConfiguratGUI
1062  // tmpCfgMgr.activateTableGroup(
1063  // tmpCfgMgr.getActiveGroupName(ConfigurationManager::GROUP_TYPE_NAME_CONTEXT),
1064  // tmpCfgMgr.getActiveGroupKey(ConfigurationManager::GROUP_TYPE_NAME_CONTEXT)
1065  // );
1066 
1067  cfgMgr->restoreActiveTableGroups(
1068  true /*throwErrors*/,
1069  "" /*pathToActiveGroupsFile*/,
1070  ConfigurationManager::LoadGroupType::
1071  ONLY_BACKBONE_OR_CONTEXT_TYPES /*onlyLoadIfBackboneOrContext*/
1072  );
1073 
1074  const std::string backboneGroupName =
1075  cfgMgr->getActiveGroupName(ConfigurationManager::GroupType::BACKBONE_TYPE);
1076 
1077  GroupEditStruct contextGroupEdit(ConfigurationManager::GroupType::CONTEXT_TYPE,
1078  cfgMgr);
1079 
1080  // Steps:
1081  // - Create record in DesktopIconTable
1082  // - Create parameter records in DesktopWindowParameterTable
1083  // - Create new Context group
1084  // - Update Aliases from old Context group to new Context group
1085  // - Activate new group
1086 
1087  TableEditStruct& iconTable = contextGroupEdit.getTableEditStruct(
1088  DesktopIconTable::ICON_TABLE, true /*markModified*/);
1089  TableEditStruct& parameterTable = contextGroupEdit.getTableEditStruct(
1090  DesktopIconTable::PARAMETER_TABLE, true /*markModified*/);
1091  TableEditStruct& appTable = contextGroupEdit.getTableEditStruct(
1092  ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME);
1093 
1094  // Create record in DesktopIconTable
1095  try
1096  {
1097  unsigned int row;
1098  std::string iconUID = "";
1099  std::string decodedCaption = StringMacros::decodeURIComponent(iconCaption);
1100 
1101  for(unsigned int i = 0; i < decodedCaption.size(); ++i)
1102  if((decodedCaption[i] >= 'a' && decodedCaption[i] <= 'z') ||
1103  (decodedCaption[i] >= 'A' && decodedCaption[i] <= 'Z') ||
1104  (decodedCaption[i] >= '0' && decodedCaption[i] <= '9'))
1105  iconUID += decodedCaption[i];
1106 
1107  // create icon record
1108  row = iconTable.tableView_->addRow(
1109  author, true /*incrementUniqueData*/, "generatedIcon" + iconUID);
1110  iconUID =
1111  iconTable.tableView_->getDataView()[row][iconTable.tableView_->getColUID()];
1112 
1113  __COUTV__(row);
1114  __COUTV__(iconUID);
1115 
1116  // set icon status true
1117  iconTable.tableView_->setValueAsString(
1118  "1", row, iconTable.tableView_->getColStatus());
1119 
1120  // set caption value
1121  iconTable.tableView_->setURIEncodedValue(
1122  iconCaption,
1123  row,
1124  iconTable.tableView_->findCol(DesktopIconTable::COL_CAPTION));
1125  // set alt text value
1126  iconTable.tableView_->setURIEncodedValue(
1127  iconAltText,
1128  row,
1129  iconTable.tableView_->findCol(DesktopIconTable::COL_ALTERNATE_TEXT));
1130  // set force one instance value
1131  iconTable.tableView_->setValueAsString(
1132  enforceOneWindowInstance ? "1" : "0",
1133  row,
1134  iconTable.tableView_->findCol(DesktopIconTable::COL_FORCE_ONLY_ONE_INSTANCE));
1135  // set permissions value
1136  iconTable.tableView_->setURIEncodedValue(
1137  iconPermissions,
1138  row,
1139  iconTable.tableView_->findCol(DesktopIconTable::COL_PERMISSIONS));
1140  // set image URL value
1141  iconTable.tableView_->setURIEncodedValue(
1142  iconImageURL,
1143  row,
1144  iconTable.tableView_->findCol(DesktopIconTable::COL_IMAGE_URL));
1145  // set window URL value
1146  iconTable.tableView_->setURIEncodedValue(
1147  iconWindowURL,
1148  row,
1149  iconTable.tableView_->findCol(DesktopIconTable::COL_WINDOW_CONTENT_URL));
1150  // set folder value
1151  iconTable.tableView_->setURIEncodedValue(
1152  iconFolderPath,
1153  row,
1154  iconTable.tableView_->findCol(DesktopIconTable::COL_FOLDER_PATH));
1155 
1156  // create link to icon app
1157  if(windowLinkedAppLID > 0)
1158  {
1159  __COUTV__(windowLinkedAppLID);
1160 
1161  int appRow = appTable.tableView_->findRow(
1162  appTable.tableView_->findCol(XDAQContextTable::colApplication_.colId_),
1163  windowLinkedAppLID);
1164  windowLinkedApp =
1165  appTable.tableView_
1166  ->getDataView()[appRow][appTable.tableView_->getColUID()];
1167  __COUT__ << "Found app by LID: " << windowLinkedApp << __E__;
1168  } // end linked app LID handling
1169 
1170  if(windowLinkedApp != "" && windowLinkedApp != "undefined" &&
1171  windowLinkedApp != TableViewColumnInfo::DATATYPE_STRING_DEFAULT)
1172  {
1173  // first check that UID exists
1174  // if not, interpret as app class type and
1175  // check for unique 'enabled' app with class type
1176  __COUTV__(windowLinkedApp);
1177 
1178  if(!windowLinkedAppLID) // no need to check if LID lookup happened already
1179  {
1180  try
1181  {
1182  windowLinkedApp = StringMacros::decodeURIComponent(windowLinkedApp);
1183  /* int appRow = */ appTable.tableView_->findRow(
1184  appTable.tableView_->getColUID(), windowLinkedApp);
1185  }
1186  catch(const std::runtime_error& e)
1187  {
1188  // attempt to treat like class, and take first match
1189  try
1190  {
1191  int appRow = appTable.tableView_->findRow(
1192  appTable.tableView_->findCol(
1193  XDAQContextTable::colApplication_.colClass_),
1194  windowLinkedApp);
1195  windowLinkedApp =
1196  appTable.tableView_
1197  ->getDataView()[appRow][appTable.tableView_->getColUID()];
1198  }
1199  catch(...)
1200  {
1201  // failed to treat like class, so throw original
1202  __SS__ << "Failed to create an icon linking to app '"
1203  << windowLinkedApp
1204  << ".' The following error occurred: " << e.what()
1205  << __E__;
1206  appTable.tableView_->print(ss);
1207  __SS_THROW__;
1208  }
1209  }
1210  }
1211  __COUTV__(windowLinkedApp);
1212 
1213  iconTable.tableView_->setValueAsString(
1214  ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME,
1215  row,
1216  iconTable.tableView_->findCol(DesktopIconTable::COL_APP_LINK));
1217  iconTable.tableView_->setValueAsString(
1218  windowLinkedApp,
1219  row,
1220  iconTable.tableView_->findCol(DesktopIconTable::COL_APP_LINK_UID));
1221  } // end create app link
1222 
1223  // parse parameters
1224  std::map<std::string, std::string> parameters;
1225 
1226  __COUTV__(windowParameters);
1227  StringMacros::getMapFromString(windowParameters, parameters);
1228 
1229  // create link to icon parameters
1230  if(parameters.size())
1231  {
1232  // set parameter link table
1233  iconTable.tableView_->setValueAsString(
1234  DesktopIconTable::PARAMETER_TABLE,
1235  row,
1236  iconTable.tableView_->findCol(DesktopIconTable::COL_PARAMETER_LINK));
1237  // set parameter link Group ID
1238  iconTable.tableView_->setValueAsString(
1239  iconUID + "_Parameters",
1240  row,
1241  iconTable.tableView_->findCol(DesktopIconTable::COL_PARAMETER_LINK_GID));
1242 
1243  __COUTV__(StringMacros::mapToString(parameters));
1244 
1245  unsigned int gidCol =
1246  parameterTable.tableView_->findCol(DesktopIconTable::COL_PARAMETER_GID);
1247 
1248  // remove all existing records from groupID (e.g. parameters leftover from manual manipulations)
1249  std::vector<unsigned int /*row*/> rowsInGroup =
1250  parameterTable.tableView_->getGroupRows(
1251  gidCol, iconUID + "_Parameters" /*groupID*/);
1252 
1253  __COUTV__(StringMacros::vectorToString(rowsInGroup));
1254 
1255  // go through vector backwards to maintain row integrity
1256  for(unsigned int r = rowsInGroup.size() - 1; r < rowsInGroup.size(); --r)
1257  parameterTable.tableView_->removeRowFromGroup(
1258  rowsInGroup[r],
1259  gidCol,
1260  iconUID + "_Parameters" /*groupID*/,
1261  true /*deleteRowIfNoGroupLeft*/);
1262 
1263  // create new parameters
1264  for(const auto& parameter : parameters)
1265  {
1266  // create parameter record
1267  row = parameterTable.tableView_->addRow(
1268  author, true /*incrementUniqueData*/, "generatedParameter");
1269 
1270  // set parameter status true
1271  parameterTable.tableView_->setValueAsString(
1272  "1", row, parameterTable.tableView_->getColStatus());
1273  // set parameter Group ID
1274  parameterTable.tableView_->setValueAsString(
1275  iconUID + "_Parameters", row, gidCol);
1276  // set parameter key
1277  parameterTable.tableView_->setURIEncodedValue(
1278  parameter.first,
1279  row,
1280  parameterTable.tableView_->findCol(
1281  DesktopIconTable::COL_PARAMETER_KEY));
1282  // set parameter value
1283  parameterTable.tableView_->setURIEncodedValue(
1284  parameter.second,
1285  row,
1286  parameterTable.tableView_->findCol(
1287  DesktopIconTable::COL_PARAMETER_VALUE));
1288  } // end parameter loop
1289 
1290  std::stringstream ss;
1291  parameterTable.tableView_->print(ss);
1292  __COUT__ << ss.str();
1293 
1294  parameterTable.tableView_
1295  ->init(); // verify new table (throws runtime_errors)
1296 
1297  } // end create parameters link
1298 
1299  std::stringstream ss;
1300  iconTable.tableView_->print(ss);
1301  __COUT__ << ss.str();
1302 
1303  iconTable.tableView_->init(); // verify new table (throws runtime_errors)
1304  }
1305  catch(...)
1306  {
1307  __COUT__ << "Icon table errors while saving. Erasing all newly "
1308  "created table versions."
1309  << __E__;
1310 
1311  throw; // re-throw
1312  } // end catch
1313 
1314  __COUT__ << "Edits complete for new desktop icon, now making persistent tables."
1315  << __E__;
1316 
1317  // all edits are complete and tables verified
1318 
1319  // Remaining steps:
1320  // save tables
1321  // save new context group and activate it
1322  // check for aliases ...
1323  // if tables aliased.. update table aliases in backbone
1324  // if context group aliased, update group aliases in backbone
1325  // if backbone modified, save group and activate it
1326 
1327  TableGroupKey newContextKey;
1328  bool foundEquivalentContextKey;
1329  TableGroupKey newBackboneKey;
1330  bool foundEquivalentBackboneKey;
1331 
1332  contextGroupEdit.saveChanges(contextGroupEdit.originalGroupName_,
1333  newContextKey,
1334  &foundEquivalentContextKey,
1335  true /*activateNewGroup*/,
1336  true /*updateGroupAliases*/,
1337  true /*updateTableAliases*/,
1338  &newBackboneKey,
1339  &foundEquivalentBackboneKey);
1340 
1341  xmlOut.addTextElementToData("contextGroupName", contextGroupEdit.originalGroupName_);
1342  xmlOut.addTextElementToData("contextGroupKey", newContextKey.toString());
1343 
1344  xmlOut.addTextElementToData("backboneGroupName", backboneGroupName);
1345  xmlOut.addTextElementToData("backboneGroupKey", newBackboneKey.toString());
1346 
1347  // always add active table groups to xml response
1349 
1350  return true;
1351  //---------------------------------------------------
1352 
1353  if(0)
1354  {
1355  // save map of group members get context members active table versions
1356  std::map<std::string, TableVersion> contextGroupMembers;
1357  std::map<std::string, TableVersion> backboneGroupMembers;
1358  {
1359  std::map<std::string, TableVersion> activeTables =
1360  cfgMgr->getActiveVersions();
1361  for(auto& table : cfgMgr->getContextMemberNames())
1362  try
1363  {
1364  __COUT__ << table << " v" << activeTables.at(table) << __E__;
1365  contextGroupMembers[table] = activeTables.at(table);
1366  }
1367  catch(...)
1368  {
1369  __SS__
1370  << "Error! Could not find Context member table '" << table
1371  << ".' All Context members must be present to add a desktop icon."
1372  << __E__;
1373  __SS_THROW__;
1374  }
1375  for(auto& table : cfgMgr->getBackboneMemberNames())
1376  try
1377  {
1378  __COUT__ << table << " v" << activeTables.at(table) << __E__;
1379  backboneGroupMembers[table] = activeTables.at(table);
1380  }
1381  catch(...)
1382  {
1383  __SS__ << "Error! Could not find Backbone member table '" << table
1384  << ".' All Backbone members must be present to add a desktop "
1385  "icon."
1386  << __E__;
1387  __SS_THROW__;
1388  }
1389  }
1390 
1391  const std::string contextGroupName =
1392  cfgMgr->getActiveGroupName(ConfigurationManager::GroupType::CONTEXT_TYPE);
1393  const TableGroupKey originalContextGroupKey =
1394  cfgMgr->getActiveGroupKey(ConfigurationManager::GroupType::CONTEXT_TYPE);
1395  const std::string backboneGroupName =
1396  cfgMgr->getActiveGroupName(ConfigurationManager::GroupType::BACKBONE_TYPE);
1397  const TableGroupKey originalBackboneGroupKey =
1398  cfgMgr->getActiveGroupKey(ConfigurationManager::GroupType::BACKBONE_TYPE);
1399 
1400  __COUTV__(contextGroupName);
1401  __COUTV__(originalContextGroupKey);
1402  __COUTV__(backboneGroupName);
1403  __COUTV__(originalBackboneGroupKey);
1404 
1405  if(contextGroupName == "" || originalContextGroupKey.isInvalid())
1406  {
1407  __SS__ << "Error! No active Context group found. "
1408  "There must be an active Context group to add a Desktop Icon."
1409  << __E__;
1410  __SS_THROW__;
1411  }
1412 
1413  // Steps:
1414  // - Create record in DesktopIconTable
1415  // - Create parameter records in DesktopWindowParameterTable
1416  // - Create new Context group
1417  // - Update Aliases from old Context group to new Context group
1418  // - Activate new group
1419 
1420  TableEditStruct iconTable(DesktopIconTable::ICON_TABLE,
1421  cfgMgr); // Table ready for editing!
1422  TableEditStruct parameterTable(DesktopIconTable::PARAMETER_TABLE,
1423  cfgMgr); // Table ready for editing!
1424  TableEditStruct appTable(ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME,
1425  cfgMgr); // Table ready for editing!
1426 
1427  // Create record in DesktopIconTable
1428  try
1429  {
1430  unsigned int row;
1431  std::string iconUID;
1432 
1433  // create icon record
1434  row = iconTable.tableView_->addRow(
1435  author, true /*incrementUniqueData*/, "generatedIcon");
1436  iconUID = iconTable.tableView_
1437  ->getDataView()[row][iconTable.tableView_->getColUID()];
1438 
1439  __COUTV__(row);
1440  __COUTV__(iconUID);
1441 
1442  // set icon status true
1443  iconTable.tableView_->setValueAsString(
1444  "1", row, iconTable.tableView_->getColStatus());
1445 
1446  // set caption value
1447  iconTable.tableView_->setURIEncodedValue(
1448  iconCaption,
1449  row,
1450  iconTable.tableView_->findCol(DesktopIconTable::COL_CAPTION));
1451  // set alt text value
1452  iconTable.tableView_->setURIEncodedValue(
1453  iconAltText,
1454  row,
1455  iconTable.tableView_->findCol(DesktopIconTable::COL_ALTERNATE_TEXT));
1456  // set force one instance value
1457  iconTable.tableView_->setValueAsString(
1458  enforceOneWindowInstance ? "1" : "0",
1459  row,
1460  iconTable.tableView_->findCol(
1461  DesktopIconTable::COL_FORCE_ONLY_ONE_INSTANCE));
1462  // set permissions value
1463  iconTable.tableView_->setURIEncodedValue(
1464  iconPermissions,
1465  row,
1466  iconTable.tableView_->findCol(DesktopIconTable::COL_PERMISSIONS));
1467  // set image URL value
1468  iconTable.tableView_->setURIEncodedValue(
1469  iconImageURL,
1470  row,
1471  iconTable.tableView_->findCol(DesktopIconTable::COL_IMAGE_URL));
1472  // set window URL value
1473  iconTable.tableView_->setURIEncodedValue(
1474  iconWindowURL,
1475  row,
1476  iconTable.tableView_->findCol(DesktopIconTable::COL_WINDOW_CONTENT_URL));
1477  // set folder value
1478  iconTable.tableView_->setURIEncodedValue(
1479  iconFolderPath,
1480  row,
1481  iconTable.tableView_->findCol(DesktopIconTable::COL_FOLDER_PATH));
1482 
1483  // create link to icon app
1484  if(windowLinkedAppLID > 0)
1485  {
1486  __COUTV__(windowLinkedAppLID);
1487 
1488  int appRow = appTable.tableView_->findRow(
1489  appTable.tableView_->findCol(
1490  XDAQContextTable::colApplication_.colId_),
1491  windowLinkedAppLID);
1492  windowLinkedApp =
1493  appTable.tableView_
1494  ->getDataView()[appRow][appTable.tableView_->getColUID()];
1495  __COUT__ << "Found app by LID: " << windowLinkedApp << __E__;
1496  } // end linked app LID handling
1497 
1498  if(windowLinkedApp != "" && windowLinkedApp != "undefined" &&
1499  windowLinkedApp != TableViewColumnInfo::DATATYPE_STRING_DEFAULT)
1500  {
1501  // first check that UID exists
1502  // if not, interpret as app class type and
1503  // check for unique 'enabled' app with class type
1504  __COUTV__(windowLinkedApp);
1505 
1506  if(!windowLinkedAppLID) // no need to check if LID lookup happened already
1507  {
1508  try
1509  {
1510  /*int appRow =*/appTable.tableView_->findRow(
1511  appTable.tableView_->getColUID(), windowLinkedApp);
1512  }
1513  catch(const std::runtime_error& e)
1514  {
1515  // attempt to treat like class, and take first match
1516  try
1517  {
1518  int appRow = appTable.tableView_->findRow(
1519  appTable.tableView_->findCol(
1520  XDAQContextTable::colApplication_.colClass_),
1521  windowLinkedApp);
1522  windowLinkedApp =
1523  appTable.tableView_
1524  ->getDataView()[appRow]
1525  [appTable.tableView_->getColUID()];
1526  }
1527  catch(...)
1528  {
1529  // failed to treat like class, so throw original
1530  __SS__ << "Failed to create an icon linking to app '"
1531  << windowLinkedApp
1532  << ".' The following error occurred: " << e.what()
1533  << __E__;
1534  __SS_THROW__;
1535  }
1536  }
1537  }
1538  __COUTV__(windowLinkedApp);
1539 
1540  iconTable.tableView_->setValueAsString(
1541  ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME,
1542  row,
1543  iconTable.tableView_->findCol(DesktopIconTable::COL_APP_LINK));
1544  iconTable.tableView_->setValueAsString(
1545  windowLinkedApp,
1546  row,
1547  iconTable.tableView_->findCol(DesktopIconTable::COL_APP_LINK_UID));
1548  } // end create app link
1549 
1550  // parse parameters
1551  std::map<std::string, std::string> parameters;
1552 
1553  __COUTV__(windowParameters);
1554  StringMacros::getMapFromString(windowParameters, parameters);
1555 
1556  // create link to icon parameters
1557  if(parameters.size())
1558  {
1559  // set parameter link table
1560  iconTable.tableView_->setValueAsString(
1561  DesktopIconTable::PARAMETER_TABLE,
1562  row,
1563  iconTable.tableView_->findCol(DesktopIconTable::COL_PARAMETER_LINK));
1564  // set parameter link Group ID
1565  iconTable.tableView_->setValueAsString(
1566  iconUID + "_Parameters",
1567  row,
1568  iconTable.tableView_->findCol(
1569  DesktopIconTable::COL_PARAMETER_LINK_GID));
1570 
1571  __COUTV__(StringMacros::mapToString(parameters));
1572 
1573  for(const auto& parameter : parameters)
1574  {
1575  // create parameter record
1576  row = parameterTable.tableView_->addRow(
1577  author, true /*incrementUniqueData*/, "generatedParameter");
1578 
1579  // set parameter status true
1580  parameterTable.tableView_->setValueAsString(
1581  "1", row, parameterTable.tableView_->getColStatus());
1582  // set parameter Group ID
1583  parameterTable.tableView_->setValueAsString(
1584  iconUID + "_Parameters",
1585  row,
1586  parameterTable.tableView_->findCol(
1587  DesktopIconTable::COL_PARAMETER_GID));
1588  // set parameter key
1589  parameterTable.tableView_->setURIEncodedValue(
1590  parameter.first,
1591  row,
1592  parameterTable.tableView_->findCol(
1593  DesktopIconTable::COL_PARAMETER_KEY));
1594  // set parameter value
1595  parameterTable.tableView_->setURIEncodedValue(
1596  parameter.second,
1597  row,
1598  parameterTable.tableView_->findCol(
1599  DesktopIconTable::COL_PARAMETER_VALUE));
1600  } // end parameter loop
1601 
1602  std::stringstream ss;
1603  parameterTable.tableView_->print(ss);
1604  __COUT__ << ss.str();
1605 
1606  parameterTable.tableView_
1607  ->init(); // verify new table (throws runtime_errors)
1608 
1609  } // end create parameters link
1610 
1611  std::stringstream ss;
1612  iconTable.tableView_->print(ss);
1613  __COUT__ << ss.str();
1614 
1615  iconTable.tableView_->init(); // verify new table (throws runtime_errors)
1616  }
1617  catch(...)
1618  {
1619  __COUT__ << "Icon table errors while saving. Erasing all newly "
1620  "created table versions."
1621  << __E__;
1622  if(iconTable.createdTemporaryVersion_) // if temporary version created here
1623  {
1624  __COUT__ << "Erasing temporary version " << iconTable.tableName_ << "-v"
1625  << iconTable.temporaryVersion_ << __E__;
1626  // erase with proper version management
1627  cfgMgr->eraseTemporaryVersion(iconTable.tableName_,
1628  iconTable.temporaryVersion_);
1629  }
1630 
1631  if(parameterTable
1632  .createdTemporaryVersion_) // if temporary version created here
1633  {
1634  __COUT__ << "Erasing temporary version " << parameterTable.tableName_
1635  << "-v" << parameterTable.temporaryVersion_ << __E__;
1636  // erase with proper version management
1637  cfgMgr->eraseTemporaryVersion(parameterTable.tableName_,
1638  parameterTable.temporaryVersion_);
1639  }
1640 
1641  if(appTable.createdTemporaryVersion_) // if temporary version created here
1642  {
1643  __COUT__ << "Erasing temporary version " << appTable.tableName_ << "-v"
1644  << appTable.temporaryVersion_ << __E__;
1645  // erase with proper version management
1646  cfgMgr->eraseTemporaryVersion(appTable.tableName_,
1647  appTable.temporaryVersion_);
1648  }
1649 
1650  throw; // re-throw
1651  } // end catch
1652 
1653  __COUT__ << "Edits complete for new desktop icon, now making persistent tables."
1654  << __E__;
1655 
1656  // all edits are complete and tables verified
1657 
1658  // Remaining steps:
1659  // save tables
1660  // save new context group and activate it
1661  // check for aliases ...
1662  // if tables aliased.. update table aliases in backbone
1663  // if context group aliased, update group aliases in backbone
1664  // if backbone modified, save group and activate it
1665 
1666  __COUT__ << "Original version is " << iconTable.tableName_ << "-v"
1667  << iconTable.originalVersion_ << __E__;
1668  __COUT__ << "Original version is " << parameterTable.tableName_ << "-v"
1669  << parameterTable.originalVersion_ << __E__;
1670 
1671  contextGroupMembers[DesktopIconTable::ICON_TABLE] =
1673  xmlOut,
1674  cfgMgr,
1675  iconTable.tableName_,
1676  iconTable.originalVersion_,
1677  true /*make temporary*/,
1678  iconTable.table_,
1679  iconTable.temporaryVersion_,
1680  true /*ignoreDuplicates*/); // make temporary version to save persistent version properly
1681  contextGroupMembers[DesktopIconTable::PARAMETER_TABLE] =
1683  xmlOut,
1684  cfgMgr,
1685  parameterTable.tableName_,
1686  parameterTable.originalVersion_,
1687  true /*make temporary*/,
1688  parameterTable.table_,
1689  parameterTable.temporaryVersion_,
1690  true /*ignoreDuplicates*/); // make temporary version to save persistent version properly
1691 
1692  __COUT__ << "Temporary target version is " << iconTable.tableName_ << "-v"
1693  << contextGroupMembers[DesktopIconTable::ICON_TABLE] << "-v"
1694  << iconTable.temporaryVersion_ << __E__;
1695  __COUT__ << "Temporary target version is " << parameterTable.tableName_ << "-v"
1696  << contextGroupMembers[DesktopIconTable::PARAMETER_TABLE] << "-v"
1697  << parameterTable.temporaryVersion_ << __E__;
1698 
1699  contextGroupMembers[DesktopIconTable::ICON_TABLE] =
1701  xmlOut,
1702  cfgMgr,
1703  iconTable.tableName_,
1704  iconTable.originalVersion_,
1705  false /*make temporary*/,
1706  iconTable.table_,
1707  iconTable.temporaryVersion_,
1708  false /*ignoreDuplicates*/,
1709  true /*lookForEquivalent*/); // save persistent version properly
1710  contextGroupMembers[DesktopIconTable::PARAMETER_TABLE] =
1712  xmlOut,
1713  cfgMgr,
1714  parameterTable.tableName_,
1715  parameterTable.originalVersion_,
1716  false /*make temporary*/,
1717  parameterTable.table_,
1718  parameterTable.temporaryVersion_,
1719  false /*ignoreDuplicates*/,
1720  true /*lookForEquivalent*/); // save persistent version properly
1721 
1722  __COUT__ << "Final target version is " << iconTable.tableName_ << "-v"
1723  << contextGroupMembers[DesktopIconTable::ICON_TABLE] << __E__;
1724  __COUT__ << "Final target version is " << parameterTable.tableName_ << "-v"
1725  << contextGroupMembers[DesktopIconTable::PARAMETER_TABLE] << __E__;
1726 
1727  for(auto& table : contextGroupMembers)
1728  {
1729  __COUT__ << table.first << " v" << table.second << __E__;
1730  }
1731 
1732  __COUT__ << "Checking for duplicate Context groups..." << __E__;
1733  TableGroupKey newContextKey =
1734  cfgMgr->findTableGroup(contextGroupName, contextGroupMembers);
1735 
1736  if(!newContextKey.isInvalid())
1737  {
1738  __COUT__ << "Found equivalent group key (" << newContextKey << ") for "
1739  << contextGroupName << "." << __E__;
1740  xmlOut.addTextElementToData(contextGroupName + "_foundEquivalentKey",
1741  "1"); // indicator
1742  }
1743  else
1744  {
1745  newContextKey =
1746  cfgMgr->saveNewTableGroup(contextGroupName, contextGroupMembers);
1747  __COUT__ << "Saved new Context group key (" << newContextKey << ") for "
1748  << contextGroupName << "." << __E__;
1749  }
1750 
1751  xmlOut.addTextElementToData("contextGroupName", contextGroupName);
1752  xmlOut.addTextElementToData("contextGroupKey", newContextKey.toString());
1753 
1754  // check for aliases of original group key and original table version
1755 
1756  __COUT__ << "Original version is " << iconTable.tableName_ << "-v"
1757  << iconTable.originalVersion_ << __E__;
1758  __COUT__ << "Original version is " << parameterTable.tableName_ << "-v"
1759  << parameterTable.originalVersion_ << __E__;
1760 
1761  bool groupAliasChange = false;
1762  bool tableAliasChange = false;
1763 
1764  { // check group aliases ... a la
1765  // ConfigurationGUISupervisor::handleSetGroupAliasInBackboneXML
1766 
1767  TableBase* table =
1768  cfgMgr->getTableByName(ConfigurationManager::GROUP_ALIASES_TABLE_NAME);
1769  TableVersion originalVersion =
1770  backboneGroupMembers[ConfigurationManager::GROUP_ALIASES_TABLE_NAME];
1771  TableVersion temporaryVersion = table->createTemporaryView(originalVersion);
1772  TableView* tableView = table->getTemporaryView(temporaryVersion);
1773 
1774  // unsigned int col;
1775  unsigned int row = 0;
1776 
1777  std::vector<std::pair<std::string, ConfigurationTree>> aliasNodePairs =
1778  cfgMgr->getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME)
1779  .getChildren();
1780  std::string groupName, groupKey;
1781  for(auto& aliasNodePair : aliasNodePairs)
1782  {
1783  groupName = aliasNodePair.second.getNode("GroupName").getValueAsString();
1784  groupKey = aliasNodePair.second.getNode("GroupKey").getValueAsString();
1785 
1786  __COUT__ << "Group Alias: " << aliasNodePair.first << " => " << groupName
1787  << "(" << groupKey << "); row=" << row << __E__;
1788 
1789  if(groupName == contextGroupName &&
1790  TableGroupKey(groupKey) == originalContextGroupKey)
1791  {
1792  __COUT__ << "Found alias! Changing group key." << __E__;
1793 
1794  groupAliasChange = true;
1795 
1796  tableView->setValueAsString(
1797  newContextKey.toString(), row, tableView->findCol("GroupKey"));
1798  }
1799 
1800  ++row;
1801  }
1802 
1803  if(groupAliasChange)
1804  {
1805  std::stringstream ss;
1806  tableView->print(ss);
1807  __COUT__ << ss.str();
1808 
1809  // save or find equivalent
1810  backboneGroupMembers[ConfigurationManager::GROUP_ALIASES_TABLE_NAME] =
1812  xmlOut,
1813  cfgMgr,
1814  table->getTableName(),
1815  originalVersion,
1816  false /*makeTemporary*/,
1817  table,
1818  temporaryVersion,
1819  false /*ignoreDuplicates*/,
1820  true /*lookForEquivalent*/);
1821 
1822  __COUT__ << "Original version is " << table->getTableName() << "-v"
1823  << originalVersion << " and new version is v"
1824  << backboneGroupMembers
1825  [ConfigurationManager::GROUP_ALIASES_TABLE_NAME]
1826  << __E__;
1827  }
1828 
1829  } // end group alias check
1830 
1831  { // check version aliases
1832 
1833  TableBase* table =
1834  cfgMgr->getTableByName(ConfigurationManager::VERSION_ALIASES_TABLE_NAME);
1835  TableVersion originalVersion =
1836  backboneGroupMembers[ConfigurationManager::VERSION_ALIASES_TABLE_NAME];
1837  TableVersion temporaryVersion = table->createTemporaryView(originalVersion);
1838  TableView* tableView = table->getTemporaryView(temporaryVersion);
1839 
1840  // unsigned int col;
1841  unsigned int row = 0;
1842 
1843  std::vector<std::pair<std::string, ConfigurationTree>> aliasNodePairs =
1844  cfgMgr->getNode(ConfigurationManager::VERSION_ALIASES_TABLE_NAME)
1845  .getChildren();
1846  std::string tableName, tableVersion;
1847  for(auto& aliasNodePair : aliasNodePairs)
1848  {
1849  tableName = aliasNodePair.second.getNode("TableName").getValueAsString();
1850  tableVersion = aliasNodePair.second.getNode("Version").getValueAsString();
1851 
1852  __COUT__ << "Table Alias: " << aliasNodePair.first << " => " << tableName
1853  << "-v" << tableVersion << "" << __E__;
1854 
1855  if(tableName == DesktopIconTable::ICON_TABLE &&
1856  TableVersion(tableVersion) == iconTable.originalVersion_)
1857  {
1858  __COUT__ << "Found alias! Changing icon table version alias."
1859  << __E__;
1860 
1861  tableAliasChange = true;
1862 
1863  tableView->setValueAsString(
1864  contextGroupMembers[DesktopIconTable::ICON_TABLE].toString(),
1865  row,
1866  tableView->findCol("Version"));
1867  }
1868  else if(tableName == DesktopIconTable::PARAMETER_TABLE &&
1869  TableVersion(tableVersion) == parameterTable.originalVersion_)
1870  {
1871  __COUT__
1872  << "Found alias! Changing icon parameter table version alias."
1873  << __E__;
1874 
1875  tableAliasChange = true;
1876 
1877  tableView->setValueAsString(
1878  contextGroupMembers[DesktopIconTable::PARAMETER_TABLE].toString(),
1879  row,
1880  tableView->findCol("Version"));
1881  }
1882 
1883  ++row;
1884  }
1885 
1886  if(tableAliasChange)
1887  {
1888  std::stringstream ss;
1889  tableView->print(ss);
1890  __COUT__ << ss.str();
1891 
1892  // save or find equivalent
1893  backboneGroupMembers[ConfigurationManager::VERSION_ALIASES_TABLE_NAME] =
1895  xmlOut,
1896  cfgMgr,
1897  table->getTableName(),
1898  originalVersion,
1899  false /*makeTemporary*/,
1900  table,
1901  temporaryVersion,
1902  false /*ignoreDuplicates*/,
1903  true /*lookForEquivalent*/);
1904 
1905  __COUT__ << "Original version is " << table->getTableName() << "-v"
1906  << originalVersion << " and new version is v"
1907  << backboneGroupMembers
1908  [ConfigurationManager::VERSION_ALIASES_TABLE_NAME]
1909  << __E__;
1910  }
1911 
1912  } // end table version alias check
1913 
1914  // if backbone modified, save group and activate it
1915  if(groupAliasChange || tableAliasChange)
1916  {
1917  for(auto& table : backboneGroupMembers)
1918  {
1919  __COUT__ << table.first << " v" << table.second << __E__;
1920  }
1921  }
1922 
1923  __COUT__ << "Checking for duplicate Backbone groups..." << __E__;
1924  TableGroupKey newBackboneKey =
1925  cfgMgr->findTableGroup(backboneGroupName, backboneGroupMembers);
1926 
1927  if(!newBackboneKey.isInvalid())
1928  {
1929  __COUT__ << "Found equivalent group key (" << newBackboneKey << ") for "
1930  << backboneGroupName << "." << __E__;
1931  xmlOut.addTextElementToData(backboneGroupName + "_foundEquivalentKey",
1932  "1" /*indicator*/);
1933  }
1934  else
1935  {
1936  newBackboneKey =
1937  cfgMgr->saveNewTableGroup(backboneGroupName, backboneGroupMembers);
1938  __COUT__ << "Saved new Backbone group key (" << newBackboneKey << ") for "
1939  << backboneGroupName << "." << __E__;
1940  }
1941 
1942  xmlOut.addTextElementToData("backboneGroupName", backboneGroupName);
1943  xmlOut.addTextElementToData("backboneGroupKey", newBackboneKey.toString());
1944 
1945  // Now need to activate Context and Backbone group
1946  __COUT__ << "Activating Context group key (" << newContextKey << ") for "
1947  << contextGroupName << "." << __E__;
1948  __COUT__ << "Activating Backbone group key (" << newBackboneKey << ") for "
1949  << backboneGroupName << "." << __E__;
1950 
1951  // acquire all active groups and ignore errors, so that activateTableGroup does not
1952  // erase other active groups
1953  cfgMgr->restoreActiveTableGroups(
1954  false /*throwErrors*/,
1955  "" /*pathToActiveGroupsFile*/,
1956  ConfigurationManager::LoadGroupType::ALL_TYPES /*onlyLoadIfBackboneOrContext*/
1957  );
1958 
1959  // activate group
1960  cfgMgr->activateTableGroup(contextGroupName, newContextKey);
1961  cfgMgr->activateTableGroup(backboneGroupName, newBackboneKey);
1962 
1963  // always add active table groups to xml response
1965  }
1966  return true;
1967 } // end handleAddDesktopIconXML()
1968 catch(std::runtime_error& e)
1969 {
1970  __SS__ << "Error adding Desktop Icon!\n\n " << e.what() << __E__;
1971  __COUT__ << "\n" << ss.str() << __E__;
1972  xmlOut.addTextElementToData("Error", ss.str());
1973  return false;
1974 }
1975 catch(...)
1976 {
1977  __SS__ << "Error adding Desktop Icon!" << __E__;
1978  try
1979  {
1980  throw;
1981  } //one more try to printout extra info
1982  catch(const std::exception& e)
1983  {
1984  ss << "Exception message: " << e.what();
1985  }
1986  catch(...)
1987  {
1988  }
1989  __COUT__ << "\n" << ss.str() << __E__;
1990  xmlOut.addTextElementToData("Error", ss.str());
1991  return false;
1992 } // end handleAddDesktopIconXML() catch
1993 
1994 //==============================================================================
1995 void ConfigurationSupervisorBase::recursiveCopyTreeUIDNode(
1996  HttpXmlDocument& xmlOut,
1997  ConfigurationManagerRW* cfgMgr,
1998  std::map<std::string /*modified table*/, TableVersion /* modified version */>&
1999  modifiedTablesMap,
2000  const unsigned int startingDepth,
2001  const unsigned int depth,
2002  const unsigned int numberOfInstances,
2003  TableView* cfgView,
2004  const std::string& uidToCopy)
2005 try
2006 {
2007  __COUTV__(startingDepth);
2008  __COUTV__(depth);
2009  __COUTV__(numberOfInstances);
2010 
2011  // throw std::runtime_error("hello");
2012 
2013  // Steps:
2014  // Assume temporary table version already created correctly for recursive level
2015  // Assume already decided it is correct to copy record at row parameter
2016  // Assume after modifications the version saving is handled above this function call
2017  // 1. copy the target row
2018  // - if depth,
2019  // 2. - check source row, for secondary copies through links
2020  // - if a link is found, check that there is not unanimous pointing by siblings
2021  // -- if unanimous pointing by siblings, do not do secondary copy, just point
2022  // 3. -- if not unanimous,
2023  // * use/create temporary version of child table
2024  // * for each instance
2025  // - recursive secondary copy (depth-1)
2026  // * save child table
2027  //
2028 
2029  // Step 1. copy the target row
2030  unsigned int col = cfgView->getColUID();
2031  unsigned int row = cfgView->findRow(col, uidToCopy);
2032 
2033  __COUT__ << "Copying " << cfgView->getTableName() << " v" << cfgView->getVersion()
2034  << " row=" << row << " record=" << uidToCopy
2035  << " instances=" << numberOfInstances << __E__;
2036 
2037  cfgView->print();
2038  // for(unsigned int i = 0; i < numberOfInstances; ++i)
2039  cfgView->copyRows(cfgMgr->getUsername(),
2040  *cfgView /*source table*/,
2041  row,
2042  1 /*srcRowsToCopy*/,
2043  -1 /*destOffsetRow*/,
2044  true /*generateUniqueDataColumns*/,
2045  uidToCopy /*baseNameAutoUID*/); // make the name similar
2046 
2047  // if no secondary copies, done now
2048  // check for secondary copies
2049  return;
2050 
2051  // secondary table copies
2052  std::string tableName = "secondary";
2053  TableVersion version(modifiedTablesMap.at(tableName));
2054 
2055  TableBase* table = cfgMgr->getTableByName(tableName);
2056  try
2057  {
2058  table->setActiveView(version);
2059  }
2060  catch(...)
2061  {
2062  if(version.isTemporaryVersion())
2063  throw; // if temporary, there is no hope to find lost version
2064 
2065  __COUT__ << "Failed to find stored version, so attempting to "
2066  "load version: "
2067  << tableName << " v" << version << __E__;
2068  cfgMgr->getVersionedTableByName(tableName, version);
2069  }
2070 
2071  __COUT__ << tableName << " active version is " << table->getViewVersion() << __E__;
2072 
2073  if(version != table->getViewVersion())
2074  {
2075  __SS__ << "Target table version (" << version
2076  << ") is not the currently active version (" << table->getViewVersion()
2077  << "). Try refreshing the tree." << __E__;
2078  __SS_THROW__;
2079  }
2080 
2081  // version handling:
2082  // always make a new temporary-version from source-version
2083  // edit temporary-version
2084  // if edit fails
2085  // delete temporary-version
2086  // else
2087  // return new temporary-version
2088  // if source-version was temporary
2089  // then delete source-version
2090  TableVersion temporaryVersion = table->createTemporaryView(version);
2091 
2092  __COUT__ << "Created temporary version " << temporaryVersion << __E__;
2093 
2094  cfgView = table->getTemporaryView(temporaryVersion);
2095  cfgView->init(); // prepare maps
2096 
2097  try // while editing
2098  {
2099  // edit...
2100 
2101  cfgView->init(); // verify new table (throws runtime_errors)
2102  }
2103  catch(...) // erase temporary view before re-throwing error
2104  {
2105  __COUT__ << "Caught error while editing. Erasing temporary version." << __E__;
2106  table->eraseView(temporaryVersion);
2107  throw;
2108  }
2109 
2111  xmlOut,
2112  cfgMgr,
2113  tableName,
2114  version,
2115  true /*make temporary*/,
2116  table,
2117  temporaryVersion,
2118  true /*ignoreDuplicates*/); // save temporary version properly
2119 }
2120 catch(std::runtime_error& e)
2121 {
2122  __SS__ << ("Error copying tree target '" + uidToCopy + "' at depth " +
2123  std::to_string(startingDepth - depth) + " in table '" +
2124  cfgView->getTableName() + ".' " + std::string(e.what()))
2125  << __E__;
2126  __COUT__ << "\n" << ss.str() << __E__;
2127  xmlOut.addTextElementToData("Error", ss.str());
2128 }
2129 catch(...)
2130 {
2131  __SS__ << ("Error copying tree target '" + uidToCopy + "' at depth " +
2132  std::to_string(startingDepth - depth) + " in table '" +
2133  cfgView->getTableName() + ".' ")
2134  << __E__;
2135  try
2136  {
2137  throw;
2138  } //one more try to printout extra info
2139  catch(const std::exception& e)
2140  {
2141  ss << "Exception message: " << e.what();
2142  }
2143  catch(...)
2144  {
2145  }
2146  __COUT__ << "\n" << ss.str() << __E__;
2147  xmlOut.addTextElementToData("Error", ss.str());
2148 } // end recursiveCopyTreeUIDNode
void loadTableGroup(const std::string &tableGroupName, const TableGroupKey &tableGroupKey, bool doActivate=false, std::map< std::string, TableVersion > *groupMembers=0, ProgressBar *progressBar=0, std::string *accumulateWarnings=0, std::string *groupComment=0, std::string *groupAuthor=0, std::string *groupCreateTime=0, bool doNotLoadMember=false, std::string *groupTypeString=0, std::map< std::string, std::string > *groupAliases=0, ConfigurationManager::LoadGroupType onlyLoadIfBackboneOrContext=ConfigurationManager::LoadGroupType::ALL_TYPES, bool ignoreVersionTracking=false)
void restoreActiveTableGroups(bool throwErrors=false, const std::string &pathToActiveGroupsFile="", ConfigurationManager::LoadGroupType onlyLoadIfBackboneOrContext=ConfigurationManager::LoadGroupType::ALL_TYPES, std::string *accumulatedWarnings=0)
std::map< std::string, std::pair< std::string, TableGroupKey > > getActiveTableGroups(void) const
void loadMemberMap(const std::map< std::string, TableVersion > &memberMap, std::string *accumulateWarnings=0)
std::map< std::string, TableVersion > getActiveVersions(void) const
getActiveVersions
ConfigurationTree getNode(const std::string &nodeString, bool doNotThrowOnBrokenUIDLinks=false) const
"root/parent/parent/"
void init(std::string *accumulatedErrors=0, bool initForWriteAccess=false, std::string *accumulatedWarnings=0)
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, TableVersion > *memberMap=0, std::string *accumulatedTreeErrors=0) const
TableGroupKey findTableGroup(const std::string &groupName, const std::map< std::string, TableVersion > &groupMembers, const std::map< std::string, std::string > &groupAliases=std::map< std::string, std::string >())
const std::map< std::string, TableInfo > & getAllTableInfo(bool refresh=false, std::string *accumulatedWarnings=0, const std::string &errorFilterName="", bool getGroupKeys=false, bool getGroupInfo=false, bool initializeActiveGroups=false)
TableGroupKey saveNewTableGroup(const std::string &groupName, std::map< std::string, TableVersion > &groupMembers, const std::string &groupComment=TableViewColumnInfo::DATATYPE_COMMENT_DEFAULT, std::map< std::string, std::string > *groupAliases=0)
modifiers of a table group based on alias, e.g. "Physics"
void activateTableGroup(const std::string &tableGroupName, TableGroupKey tableGroupKey, std::string *accumulatedTreeErrors=0, std::string *groupTypeString=0)
modifiers of table groups
TableVersion saveModifiedVersion(const std::string &tableName, TableVersion originalVersion, bool makeTemporary, TableBase *config, TableVersion temporaryModifiedVersion, bool ignoreDuplicates=false, bool lookForEquivalent=false, bool *foundEquivalent=nullptr)
const GroupInfo & getGroupInfo(const std::string &groupName)
public group cache handling
const std::string & getUsername(void) const
Getters.
std::map< std::string, std::map< std::string, TableVersion > > getVersionAliases(void) const
void eraseTemporaryVersion(const std::string &tableName, TableVersion targetVersion=TableVersion())
TableBase * getVersionedTableByName(const std::string &tableName, TableVersion version, bool looseColumnMatching=false, std::string *accumulatedErrors=0, bool getRawData=false)
static void getConfigurationStatusXML(HttpXmlDocument &xmlOut, ConfigurationManagerRW *cfgMgr, const std::string &username)
getConfigurationStatusXML
static TableVersion saveModifiedVersionXML(HttpXmlDocument &xmlOut, ConfigurationManagerRW *cfgMgr, const std::string &tableName, TableVersion originalVersion, bool makeTemporary, TableBase *config, TableVersion temporaryModifiedVersion, bool ignoreDuplicates=false, bool lookForEquivalent=false)
static void handleGetTableGroupXML(HttpXmlDocument &xmlOut, ConfigurationManagerRW *cfgMgr, const std::string &groupName, TableGroupKey groupKey, bool ignoreWarnings=false)
static void handleCreateTableXML(HttpXmlDocument &xmlOut, ConfigurationManagerRW *cfgMgr, const std::string &tableName, TableVersion version, bool makeTemporary, const std::string &data, const int &dataOffset, const std::string &author, const std::string &comment, bool sourceTableAsIs, bool lookForEquivalent)
static void handleCreateTableGroupXML(HttpXmlDocument &xmlOut, ConfigurationManagerRW *cfgMgr, const std::string &groupName, const std::string &configList, bool allowDuplicates=false, bool ignoreWarnings=false, const std::string &groupComment="", bool lookForEquivalent=false)
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool byPriority=false, bool onlyStatusTrue=false) const
const std::string & getTableName(void) const
Getters.
Definition: TableBase.cc:681
TableVersion createTemporaryView(TableVersion sourceViewVersion=TableVersion(), TableVersion destTemporaryViewVersion=TableVersion::getNextTemporaryVersion())
source of -1, from MockUp, else from valid view version
Definition: TableBase.cc:1601
TableView * getTemporaryView(TableVersion temporaryVersion)
Definition: TableBase.cc:1712
const TableVersion & getViewVersion(void) const
always the active one
Definition: TableBase.cc:690
std::string toString(void) const
toString
bool isInvalid(void) const
isInvalid
bool isMockupVersion(void) const
std::string toString(void) const
toString
Definition: TableVersion.cc:33
bool isInvalid(void) const
isInvalid
bool isScratchVersion(void) const
bool isTemporaryVersion(void) const
unsigned int findRow(unsigned int col, const T &value, unsigned int offsetRow=0, bool doNotThrow=false) const
< in included .icc source
void setValueAsString(const std::string &value, unsigned int row, unsigned int col)
Definition: TableView.cc:1078
unsigned int getColStatus(void) const
Definition: TableView.cc:1390
int fillFromCSV(const std::string &data, const int &dataOffset=0, const std::string &author="")
Definition: TableView.cc:3111
bool removeRowFromGroup(const unsigned int &row, const unsigned int &col, const std::string &groupID, bool deleteRowIfNoGroupLeft=false)
Definition: TableView.cc:1582
unsigned int copyRows(const std::string &author, const TableView &src, unsigned int srcOffsetRow=0, unsigned int srcRowsToCopy=(unsigned int) -1, unsigned int destOffsetRow=(unsigned int) -1, unsigned char generateUniqueDataColumns=false, const std::string &baseNameAutoUID="")
Definition: TableView.cc:125
void init(void)
Definition: TableView.cc:189
std::vector< unsigned int > getGroupRows(const unsigned int groupIdCol, const std::string &groupID, bool onlyStatusTrue=false, bool orderedByPriority=false) const
Definition: TableView.cc:1480
unsigned int getDataColumnSize(void) const
getDataColumnSize
Definition: TableView.cc:1976
unsigned int getColUID(void) const
Definition: TableView.cc:1305
bool setURIEncodedValue(const std::string &value, const unsigned int &row, const unsigned int &col, const std::string &author="")
Definition: TableView.cc:3247
unsigned int findCol(const std::string &name) const
Definition: TableView.cc:1935
void setURIEncodedComment(const std::string &uriComment)
Definition: TableView.cc:2091
unsigned int addRow(const std::string &author="", unsigned char incrementUniqueData=false, const std::string &baseNameAutoUID="", unsigned int rowToAdd=(unsigned int) -1, std::string childLinkIndex="", std::string groupId="")
Definition: TableView.cc:3339
xercesc::DOMElement * addTextElementToParent(const std::string &childName, const std::string &childText, xercesc::DOMElement *parent)
Definition: XmlDocument.cc:190
static std::string setToString(const std::set< T > &setToReturn, const std::string &delimeter=", ")
setToString ~
static std::string vectorToString(const std::vector< T > &setToReturn, const std::string &delimeter=", ")
vectorToString ~
static std::string mapToString(const std::map< std::string, T > &mapToReturn, const std::string &primaryDelimeter=", ", const std::string &secondaryDelimeter=": ")
static void getMapFromString(const std::string &inputString, std::map< S, T > &mapToReturn, const std::set< char > &pairPairDelimiter={',', '|', '&'}, const std::set< char > &nameValueDelimiter={'=', ':'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'})
getMapFromString ~
static std::string decodeURIComponent(const std::string &data)
TableBase * table_
everything needed for editing a table
bool createdTemporaryVersion_
indicates if temp version was created here