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