otsdaq  v2_05_02_indev
TableViewColumnInfo.cc
1 #include "otsdaq/TableCore/TableViewColumnInfo.h"
2 
3 #include "otsdaq/Macros/CoutMacros.h"
4 #include "otsdaq/Macros/StringMacros.h"
5 
6 #include <iostream>
7 #include <sstream>
8 #include <stdexcept>
9 
10 #include "otsdaq/TableCore/TableView.h"
11 
12 using namespace ots;
13 
14 // clang-format off
15 
16 // NOTE: Do NOT put '-' in static const TYPEs because it will mess up javascript handling
17 // in the web gui
18 const std::string TableViewColumnInfo::TYPE_UID = "UID";
19 
20 const std::string TableViewColumnInfo::TYPE_DATA = "Data";
21 const std::string TableViewColumnInfo::TYPE_UNIQUE_DATA = "UniqueData";
22 const std::string TableViewColumnInfo::TYPE_UNIQUE_GROUP_DATA = "UniqueGroupData";
23 const std::string TableViewColumnInfo::TYPE_MULTILINE_DATA = "MultilineData";
24 const std::string TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA = "FixedChoiceData";
25 const std::string TableViewColumnInfo::TYPE_BITMAP_DATA = "BitMap";
26 
27 const std::string TableViewColumnInfo::TYPE_ON_OFF = "OnOff";
28 const std::string TableViewColumnInfo::TYPE_TRUE_FALSE = "TrueFalse";
29 const std::string TableViewColumnInfo::TYPE_YES_NO = "YesNo";
30 
31 const std::string TableViewColumnInfo::TYPE_START_CHILD_LINK = "ChildLink";
32 const std::string TableViewColumnInfo::TYPE_START_CHILD_LINK_UID = "ChildLinkUID";
33 const std::string TableViewColumnInfo::TYPE_START_CHILD_LINK_GROUP_ID = "ChildLinkGroupID";
34 const std::string TableViewColumnInfo::TYPE_START_GROUP_ID = "GroupID";
35 const std::string TableViewColumnInfo::TYPE_COMMENT = "Comment";
36 const std::string TableViewColumnInfo::TYPE_AUTHOR = "Author";
37 const std::string TableViewColumnInfo::TYPE_TIMESTAMP = "Timestamp";
38 // NOTE: Do NOT put '-' in static const TYPEs because it will mess up javascript handling
39 // in the web gui
40 
41 const std::string TableViewColumnInfo::DATATYPE_NUMBER = "NUMBER";
42 const std::string TableViewColumnInfo::DATATYPE_STRING = "STRING";
43 const std::string TableViewColumnInfo::DATATYPE_TIME = "TIMESTAMP WITH TIMEZONE";
44 
45 const std::string TableViewColumnInfo::TYPE_VALUE_YES = "Yes";
46 const std::string TableViewColumnInfo::TYPE_VALUE_NO = "No";
47 const std::string TableViewColumnInfo::TYPE_VALUE_TRUE = "True";
48 const std::string TableViewColumnInfo::TYPE_VALUE_FALSE = "False";
49 const std::string TableViewColumnInfo::TYPE_VALUE_ON = "On";
50 const std::string TableViewColumnInfo::TYPE_VALUE_OFF = "Off";
51 
52 const std::string TableViewColumnInfo::DATATYPE_STRING_DEFAULT = "DEFAULT";
53 const std::string TableViewColumnInfo::DATATYPE_COMMENT_DEFAULT = "No Comment";
54 const std::string TableViewColumnInfo::DATATYPE_BOOL_DEFAULT = "0";
55 const std::string TableViewColumnInfo::DATATYPE_NUMBER_DEFAULT = "0";
56 const std::string TableViewColumnInfo::DATATYPE_TIME_DEFAULT = "0";
57 const std::string TableViewColumnInfo::DATATYPE_LINK_DEFAULT = "NO_LINK";
58 
59 const std::string TableViewColumnInfo::COL_NAME_STATUS = "Status";
60 const std::string TableViewColumnInfo::COL_NAME_ENABLED = "Enabled";
61 const std::string TableViewColumnInfo::COL_NAME_PRIORITY = "Priority";
62 const std::string TableViewColumnInfo::COL_NAME_COMMENT = "CommentDescription";
63 const std::string TableViewColumnInfo::COL_NAME_AUTHOR = "Author";
64 const std::string TableViewColumnInfo::COL_NAME_CREATION = "RecordInsertionTime";
65 
66 // clang-format on
67 
68 //==============================================================================
69 // TableViewColumnInfo
70 // if(capturedExceptionString) *capturedExceptionString = ""; //indicates no error found
71 // if(!capturedExceptionString) then exception is thrown on error
72 TableViewColumnInfo::TableViewColumnInfo(const std::string& type,
73  const std::string& name,
74  const std::string& storageName,
75  const std::string& dataType,
76  const std::string& dataChoicesCSV,
77  std::string* capturedExceptionString)
78  : type_(type), name_(name), storageName_(storageName), dataType_(dataType), bitMapInfoP_(0)
79 {
80  // verify type
81  if ((type_ != TYPE_UID) && (type_ != TYPE_DATA) && (type_ != TYPE_UNIQUE_DATA) && (type_ != TYPE_UNIQUE_GROUP_DATA) && (type_ != TYPE_MULTILINE_DATA) &&
82  (type_ != TYPE_FIXED_CHOICE_DATA) && (type_ != TYPE_BITMAP_DATA) && (type_ != TYPE_ON_OFF) && (type_ != TYPE_TRUE_FALSE) && (type_ != TYPE_YES_NO) &&
83  (type_ != TYPE_COMMENT) && (type_ != TYPE_AUTHOR) && (type_ != TYPE_TIMESTAMP) && !isChildLink() && !isChildLinkUID() && !isChildLinkGroupID() &&
84  !isGroupID())
85  {
86  __SS__ << "The type for column " << name_ << " is " << type_ << ", while the only accepted types are: " << TYPE_DATA << " " << TYPE_UNIQUE_DATA << " "
87  << TYPE_UNIQUE_GROUP_DATA << " " << TYPE_MULTILINE_DATA << " " << TYPE_FIXED_CHOICE_DATA << " " << TYPE_UID << " " << TYPE_ON_OFF << " "
88  << TYPE_TRUE_FALSE << " " << TYPE_YES_NO << " " << TYPE_START_CHILD_LINK << "-* " << TYPE_START_CHILD_LINK_UID << "-* "
89  << TYPE_START_CHILD_LINK_GROUP_ID << "-* " << TYPE_START_GROUP_ID << "-* " << std::endl;
90  if (capturedExceptionString)
91  *capturedExceptionString = ss.str();
92  else
93  __SS_THROW__;
94  }
95  else if (capturedExceptionString)
96  *capturedExceptionString = ""; // indicates no error found
97 
98  // enforce that type only
99  // allows letters, numbers, dash, underscore
100  for (unsigned int i = 0; i < type_.size(); ++i)
101  if (!((type_[i] >= 'A' && type_[i] <= 'Z') || (type_[i] >= 'a' && type_[i] <= 'z') || (type_[i] >= '0' && type_[i] <= '9') ||
102  (type_[i] == '-' || type_[i] == '_' || type_[i] == '.' || type_[i] == ' ')))
103  {
104  __SS__ << "The column type for column " << name_ << " is '" << type_ << "'. Column types must contain only letters, numbers, "
105  << "dashes, underscores, periods, and spaces." << std::endl;
106  if (capturedExceptionString)
107  *capturedExceptionString += ss.str();
108  else
109  __SS_THROW__;
110  }
111 
112  // verify data type
113 
114  // first, convert antiquated
115  if (dataType_ == "VARCHAR2")
116  dataType_ = DATATYPE_STRING;
117 
118  if ((dataType_ != DATATYPE_NUMBER) && (dataType_ != DATATYPE_STRING) && (dataType_ != DATATYPE_TIME))
119  {
120  __SS__ << "The data type for column " << name_ << " is " << dataType_ << ", while the only accepted types are: " << DATATYPE_NUMBER << " "
121  << DATATYPE_STRING << " " << DATATYPE_TIME << std::endl;
122  if (capturedExceptionString)
123  *capturedExceptionString += ss.str();
124  else
125  __SS_THROW__;
126  }
127 
128  if (dataType_.size() == 0)
129  {
130  __SS__ << "The data type for column " << name_ << " is '" << dataType_ << "'. Data types must contain at least 1 character." << std::endl;
131  if (capturedExceptionString)
132  *capturedExceptionString += ss.str();
133  else
134  __SS_THROW__;
135  }
136 
137  // enforce that data type only
138  // allows letters, numbers, dash, underscore
139  for (unsigned int i = 0; i < dataType_.size(); ++i)
140  if (!((dataType_[i] >= 'A' && dataType_[i] <= 'Z') || (dataType_[i] >= 'a' && dataType_[i] <= 'z') || (dataType_[i] >= '0' && dataType_[i] <= '9') ||
141  (dataType_[i] == '-' || dataType_[i] == '_' || dataType_[i] == ' ')))
142  {
143  __SS__ << "The data type for column " << name_ << " is '" << dataType_ << "'. Data types must contain only letters, numbers, "
144  << "dashes, underscores, and spaces." << std::endl;
145  if (capturedExceptionString)
146  *capturedExceptionString += ss.str();
147  else
148  __SS_THROW__;
149  }
150 
151  if (name_.size() == 0)
152  {
153  __SS__ << "There is a column named " << name_ << "'. Column names must contain at least 1 character." << std::endl;
154  if (capturedExceptionString)
155  *capturedExceptionString += ss.str();
156  else
157  __SS_THROW__;
158  }
159 
160  // enforce that col name only
161  // allows letters, numbers, dash, underscore
162  for (unsigned int i = 0; i < name_.size(); ++i)
163  if (!((name_[i] >= 'A' && name_[i] <= 'Z') || (name_[i] >= 'a' && name_[i] <= 'z') || (name_[i] >= '0' && name_[i] <= '9') ||
164  (name_[i] == '-' || name_[i] == '_')))
165  {
166  __SS__ << "There is a column named " << name_ << "'. Column names must contain only letters, numbers, "
167  << "dashes, and underscores." << std::endl;
168  if (capturedExceptionString)
169  *capturedExceptionString += ss.str();
170  else
171  __SS_THROW__;
172  }
173 
174  if (storageName_.size() == 0)
175  {
176  __SS__ << "The storage name for column " << name_ << " is '" << storageName_ << "'. Storage names must contain at least 1 character." << std::endl;
177  if (capturedExceptionString)
178  *capturedExceptionString += ss.str();
179  else
180  __SS_THROW__;
181  }
182 
183  // enforce that col storage name only
184  // allows capital letters, numbers, dash, underscore
185  for (unsigned int i = 0; i < storageName_.size(); ++i)
186  if (!((storageName_[i] >= 'A' && storageName_[i] <= 'Z') || (storageName_[i] >= '0' && storageName_[i] <= '9') ||
187  (storageName_[i] == '-' || storageName_[i] == '_')))
188  {
189  __SS__ << "The storage name for column " << name_ << " is '" << storageName_ << "'. Storage names must contain only capital letters, numbers,"
190  << "dashes, and underscores." << std::endl;
191  if (capturedExceptionString)
192  *capturedExceptionString += ss.str();
193  else
194  __SS_THROW__;
195  }
196 
197  // build data choices vector from URI encoded data
198  //__COUT__ << "dataChoicesCSV " << dataChoicesCSV << std::endl;
199  {
200  std::istringstream f(dataChoicesCSV);
201  std::string s;
202  while (getline(f, s, ','))
203  dataChoices_.push_back(StringMacros::decodeURIComponent(s));
204  // for(const auto &dc: dataChoices_)
205  // __COUT__ << dc << std::endl;
206  }
207 
208  try
209  {
210  extractBitMapInfo();
211  }
212  catch (std::runtime_error & e)
213  {
214  if (capturedExceptionString)
215  *capturedExceptionString += e.what();
216  else
217  throw;
218  }
219 
220  //__COUT__ << "dataChoicesCSV " << dataChoicesCSV << std::endl;
221 }
222 
223 //==============================================================================
224 void TableViewColumnInfo::extractBitMapInfo()
225 {
226  // create BitMapInfo if this is a bitmap column
227  if (type_ == TYPE_BITMAP_DATA)
228  {
229  if (bitMapInfoP_)
230  delete bitMapInfoP_;
231  bitMapInfoP_ = new BitMapInfo();
232 
233  // extract bitMapInfo parameters:
234  // must match TableEditor js handling:
235 
236  // [ //types => 0:string, 1:bool (default no),
237  // //2:bool (default yes), 3:color
238  //
239  // 0 0,//"Number of Rows",
240  // 1 0,//"Number of Columns",
241  // 2 0,//"Cell Bit-field Size",
242  // 3 0,//"Min-value Allowed",
243  // 4 0,//"Max-value Allowed",
244  // 5 0,//"Value step-size Allowed",
245  // 6 0,//"Display Aspect H:W",
246  // 7 3,//"Min-value Cell Color",
247  // 8 3,//"Mid-value Cell Color",
248  // 9 3,//"Max-value Cell Color",
249  // 10 3,//"Absolute Min-value Cell Color",
250  // 11 3,//"Absolute Max-value Cell Color",
251  // 12 1,//"Display Rows in Ascending Order",
252  // 13 2,//"Display Columns in Ascending Order",
253  // 14 1,//"Snake Double Rows",
254  // 15 1];//"Snake Double Columns"];
255 
256  if (dataChoices_.size() < 16)
257  {
258  __SS__ << "The Bit-Map data parameters for column " << name_ << " should be size 16, but is size " << dataChoices_.size()
259  << ". Bit-Map parameters should be rows, cols, cellBitSize, and min, "
260  "mid, max color."
261  << std::endl;
262  __SS_THROW__;
263  }
264 
265  sscanf(dataChoices_[0].c_str(), "%u", &(bitMapInfoP_->numOfRows_));
266  sscanf(dataChoices_[1].c_str(), "%u", &(bitMapInfoP_->numOfColumns_));
267  sscanf(dataChoices_[2].c_str(), "%u", &(bitMapInfoP_->cellBitSize_));
268 
269  sscanf(dataChoices_[3].c_str(), "%lu", &(bitMapInfoP_->minValue_));
270  sscanf(dataChoices_[4].c_str(), "%lu", &(bitMapInfoP_->maxValue_));
271  sscanf(dataChoices_[5].c_str(), "%lu", &(bitMapInfoP_->stepValue_));
272 
273  bitMapInfoP_->aspectRatio_ = dataChoices_[6];
274  bitMapInfoP_->minColor_ = dataChoices_[7];
275  bitMapInfoP_->midColor_ = dataChoices_[8];
276  bitMapInfoP_->maxColor_ = dataChoices_[9];
277  bitMapInfoP_->absMinColor_ = dataChoices_[10];
278  bitMapInfoP_->absMaxColor_ = dataChoices_[11];
279 
280  bitMapInfoP_->rowsAscending_ = dataChoices_[12] == "Yes" ? 1 : 0;
281  bitMapInfoP_->colsAscending_ = dataChoices_[13] == "Yes" ? 1 : 0;
282  bitMapInfoP_->snakeRows_ = dataChoices_[14] == "Yes" ? 1 : 0;
283  bitMapInfoP_->snakeCols_ = dataChoices_[15] == "Yes" ? 1 : 0;
284  }
285 }
286 
287 //==============================================================================
288 // private empty default constructor. Only used by assignment operator.
289 TableViewColumnInfo::TableViewColumnInfo(void) {}
290 
291 //==============================================================================
292 TableViewColumnInfo::TableViewColumnInfo(const TableViewColumnInfo& c) // copy constructor because of bitmap pointer
293  : type_(c.type_), name_(c.name_), storageName_(c.storageName_), dataType_(c.dataType_), dataChoices_(c.dataChoices_), bitMapInfoP_(0)
294 {
295  // extract bitmap info if necessary
296  extractBitMapInfo();
297 }
298 
299 //==============================================================================
300 TableViewColumnInfo& TableViewColumnInfo::operator=(const TableViewColumnInfo& c) // assignment operator because of bitmap pointer
301 {
302  TableViewColumnInfo* retColInfo = new TableViewColumnInfo();
303  retColInfo->type_ = c.type_;
304  retColInfo->name_ = c.name_;
305  retColInfo->storageName_ = c.storageName_;
306  retColInfo->dataType_ = c.dataType_;
307  retColInfo->dataChoices_ = c.dataChoices_;
308  retColInfo->bitMapInfoP_ = 0;
309 
310  // extract bitmap info if necessary
311  retColInfo->extractBitMapInfo();
312 
313  return *retColInfo;
314 }
315 
316 //==============================================================================
317 TableViewColumnInfo::~TableViewColumnInfo(void)
318 {
319  if (bitMapInfoP_)
320  delete bitMapInfoP_;
321 }
322 
323 //==============================================================================
324 const std::string& TableViewColumnInfo::getType(void) const { return type_; }
325 
326 //==============================================================================
327 const std::string& TableViewColumnInfo::getDefaultValue(void) const
328 {
329  if (getDataType() == TableViewColumnInfo::DATATYPE_STRING)
330  {
331  if (getType() == TableViewColumnInfo::TYPE_ON_OFF || getType() == TableViewColumnInfo::TYPE_TRUE_FALSE || getType() == TableViewColumnInfo::TYPE_YES_NO)
332  return (TableViewColumnInfo::DATATYPE_BOOL_DEFAULT); // default to OFF, NO, FALSE
333  else if (isChildLink())
334  return (TableViewColumnInfo::DATATYPE_LINK_DEFAULT);
335  else if (getType() == TableViewColumnInfo::TYPE_COMMENT)
336  return (TableViewColumnInfo::DATATYPE_COMMENT_DEFAULT);
337  else
338  return (TableViewColumnInfo::DATATYPE_STRING_DEFAULT);
339  }
340  else if (getDataType() == TableViewColumnInfo::DATATYPE_NUMBER)
341  return (TableViewColumnInfo::DATATYPE_NUMBER_DEFAULT);
342  else if (getDataType() == TableViewColumnInfo::DATATYPE_TIME)
343  return (TableViewColumnInfo::DATATYPE_TIME_DEFAULT);
344  else
345  {
346  __SS__ << "\tUnrecognized View data type: " << getDataType() << std::endl;
347  __COUT_ERR__ << "\n" << ss.str();
348  __SS_THROW__;
349  }
350 }
351 
352 //==============================================================================
353 std::vector<std::string> TableViewColumnInfo::getAllTypesForGUI(void)
354 {
355  std::vector<std::string> all;
356  all.push_back(TYPE_DATA);
357  all.push_back(TYPE_UNIQUE_DATA);
358  all.push_back(TYPE_UNIQUE_GROUP_DATA);
359  all.push_back(TYPE_FIXED_CHOICE_DATA);
360  all.push_back(TYPE_MULTILINE_DATA);
361  all.push_back(TYPE_BITMAP_DATA);
362  all.push_back(TYPE_ON_OFF);
363  all.push_back(TYPE_TRUE_FALSE);
364  all.push_back(TYPE_YES_NO);
365  all.push_back(TYPE_START_CHILD_LINK_UID);
366  all.push_back(TYPE_START_CHILD_LINK_GROUP_ID);
367  all.push_back(TYPE_START_CHILD_LINK);
368  all.push_back(TYPE_START_GROUP_ID);
369  return all;
370 }
371 
372 //==============================================================================
373 std::vector<std::string> TableViewColumnInfo::getAllDataTypesForGUI(void)
374 {
375  std::vector<std::string> all;
376  all.push_back(DATATYPE_STRING);
377  all.push_back(DATATYPE_NUMBER);
378  all.push_back(DATATYPE_TIME);
379  return all;
380 }
381 
382 //==============================================================================
383 // map of datatype,type to default value
384 std::map<std::pair<std::string, std::string>, std::string> TableViewColumnInfo::getAllDefaultsForGUI(void)
385 {
386  std::map<std::pair<std::string, std::string>, std::string> all;
387  all[std::pair<std::string, std::string>(DATATYPE_NUMBER, "*")] = DATATYPE_NUMBER_DEFAULT;
388  all[std::pair<std::string, std::string>(DATATYPE_TIME, "*")] = DATATYPE_TIME_DEFAULT;
389 
390  all[std::pair<std::string, std::string>(DATATYPE_STRING, TYPE_ON_OFF)] = DATATYPE_BOOL_DEFAULT;
391  all[std::pair<std::string, std::string>(DATATYPE_STRING, TYPE_TRUE_FALSE)] = DATATYPE_BOOL_DEFAULT;
392  all[std::pair<std::string, std::string>(DATATYPE_STRING, TYPE_YES_NO)] = DATATYPE_BOOL_DEFAULT;
393 
394  all[std::pair<std::string, std::string>(DATATYPE_STRING, TYPE_START_CHILD_LINK)] = DATATYPE_LINK_DEFAULT;
395  all[std::pair<std::string, std::string>(DATATYPE_STRING, "*")] = DATATYPE_STRING_DEFAULT;
396  return all;
397 }
398 
399 //==============================================================================
400 // isBoolType
401 bool TableViewColumnInfo::isBoolType(void) const
402 {
403  return (type_ == TYPE_ON_OFF || type_ == TYPE_TRUE_FALSE || type_ == TYPE_YES_NO);
404 } // end isBoolType()
405 
406 //==============================================================================
407 // isNumberDataType
408 bool TableViewColumnInfo::isNumberDataType(void) const { return (dataType_ == DATATYPE_NUMBER); } // end isBoolType()
409 
410 //==============================================================================
411 const std::string& TableViewColumnInfo::getName(void) const { return name_; }
412 
413 //==============================================================================
414 const std::string& TableViewColumnInfo::getStorageName(void) const { return storageName_; }
415 
416 //==============================================================================
417 const std::string& TableViewColumnInfo::getDataType(void) const { return dataType_; }
418 
419 //==============================================================================
420 const std::vector<std::string>& TableViewColumnInfo::getDataChoices(void) const { return dataChoices_; }
421 
422 //==============================================================================
423 // getBitMapInfo
424 // uses dataChoices CSV fields if type is TYPE_BITMAP_DATA
425 const TableViewColumnInfo::BitMapInfo& TableViewColumnInfo::getBitMapInfo(void) const
426 {
427  if (bitMapInfoP_)
428  return *bitMapInfoP_;
429 
430  // throw error at this point!
431  {
432  __SS__ << "getBitMapInfo request for non-BitMap column of type: " << getType() << std::endl;
433  __COUT_ERR__ << "\n" << ss.str();
434  __SS_THROW__;
435  }
436 }
437 
438 //==============================================================================
439 // isChildLink
440 // note: TYPE_START_CHILD_LINK index may be a subset of UID and GROUP_ID
441 // so don't allow alpha character immediately after
442 bool TableViewColumnInfo::isChildLink(void) const
443 {
444  return (type_.find(TYPE_START_CHILD_LINK) == 0 && type_.length() > TYPE_START_CHILD_LINK.length() && type_[TYPE_START_CHILD_LINK.length()] == '-');
445 }
446 
447 //==============================================================================
448 // isChildLinkUID
449 // note: TYPE_START_CHILD_LINK index may be a subset of UID and GROUP_ID
450 // so don't allow alpha character immediately after
451 bool TableViewColumnInfo::isChildLinkUID(void) const
452 {
453  return (type_.find(TYPE_START_CHILD_LINK_UID) == 0 && type_.length() > TYPE_START_CHILD_LINK_UID.length() &&
454  type_[TYPE_START_CHILD_LINK_UID.length()] == '-');
455 }
456 
457 //==============================================================================
458 // isChildLinkGroupID
459 // note: TYPE_START_CHILD_LINK index may be a subset of UID and GROUP_ID
460 // so don't allow alpha character immediately after
461 bool TableViewColumnInfo::isChildLinkGroupID(void) const
462 {
463  return (type_.find(TYPE_START_CHILD_LINK_GROUP_ID) == 0 && type_.length() > TYPE_START_CHILD_LINK_GROUP_ID.length() &&
464  type_[TYPE_START_CHILD_LINK_GROUP_ID.length()] == '-');
465 }
466 
467 //==============================================================================
468 // isGroupID
469 // note: TYPE_START_CHILD_LINK index may be a subset of UID and GROUP_ID
470 // so don't allow alpha character immediately after in group index
471 bool TableViewColumnInfo::isGroupID(void) const
472 {
473  return (type_.find(TYPE_START_GROUP_ID) == 0 && type_.length() > TYPE_START_GROUP_ID.length() && type_[TYPE_START_GROUP_ID.length()] == '-');
474 }
475 
476 //==============================================================================
477 // isUID
478 bool TableViewColumnInfo::isUID(void) const { return (type_ == TYPE_UID); }
479 
480 //==============================================================================
481 // getChildLinkIndex
482 std::string TableViewColumnInfo::getChildLinkIndex(void) const
483 {
484  // note: +1 to skip '-'
485  if (isChildLink())
486  return type_.substr(TYPE_START_CHILD_LINK.length() + 1);
487  else if (isChildLinkUID())
488  return type_.substr(TYPE_START_CHILD_LINK_UID.length() + 1);
489  else if (isChildLinkGroupID())
490  return type_.substr(TYPE_START_CHILD_LINK_GROUP_ID.length() + 1);
491  else if (isGroupID())
492  return type_.substr(TYPE_START_GROUP_ID.length() + 1);
493  else
494  {
495  __SS__ << ("Requesting a Link Index from a column that is not a child link member!") << std::endl;
496  __COUT_ERR__ << ss.str();
497  __SS_THROW__;
498  }
499 }