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