otsdaq  v2_01_00
ConfigurationTree.h
1 #ifndef _ots_ConfigurationTree_h_
2 #define _ots_ConfigurationTree_h_
3 
4 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationView.h"
5 
6 
7 #include <iostream> // std::cout
8 #include <string>
9 #include <set>
10 
11 
12 namespace ots
13 {
14 
15 class ConfigurationManager;
16 class ConfigurationBase;
17 class ConfigurationView;
18 
19 
20 template<typename T>
21 struct identity { typedef T type; };
22 
23 
24 //
25 //template <class T> T handleValidateValueForColumn (ConfigurationView* configView, std::string value, unsigned int col)
26 //{
27 // std::cout << "22:::::" << "handleValidateValueForColumn<T>" << std::endl;
28 // return configView->validateValueForColumn<T>(
29 // value,col);
30 //}
31 //template <> std::string handleValidateValueForColumn<std::string>(ConfigurationView* configView, std::string value, unsigned int col)
32 //{
33 // std::cout << "22:::::" << "handleValidateValueForColumn<std::string>" << std::endl;
34 // return configView->validateValueForColumn(
35 // value,col);
36 //}
37 
39 {
40  friend class ConfigurationGUISupervisor;
41  friend class Iterator;
42 
43 public:
44  //Note: due to const members, implicit copy constructor exists, but NOT assignment operator=
45  // ... so ConfigurationTree t = mytree.GetNode(nodeString); //ok
46  // ... or ConfigurationTree t(mytree.GetNode(nodeString)); //ok
47  // ... but mytree = mytree.GetNode(nodeString); //does NOT work
49 // ConfigurationTree(const ConfigurationTree& a)
50 // :
51 // configMgr_ (a.configMgr_),
52 // configuration_ (a.configuration_),
53 // groupId_ (a.groupId_),
54 // linkColName_ (a.linkColName_),
55 // disconnectedTargetName_ (a.disconnectedTargetName_),
56 // childLinkIndex_ (a.childLinkIndex_),
57 // row_ (a.row_),
58 // col_ (a.col_),
59 // configView_ (a.configView_)
60 // {
61 // __COUT__ << std::endl;
62 // //return *this;
63 // }
64 
65  ConfigurationTree (const ConfigurationManager* const& configMgr, const ConfigurationBase* const &config);
66  ~ConfigurationTree (void);
67 
68  ConfigurationTree& operator=(const ConfigurationTree& a)
69  {
70  __COUT__ << "OPERATOR= COPY CONSTRUCTOR ConfigManager: " << configMgr_ << " configuration: " << configuration_ << std::endl;
71  //Note: Members of the ConfigurationTree are declared constant.
72  // (Refer to comments at top of class declaration for solutions)
73  // So this operator cannot work.. SO I am going to crash just in case it is called by mistake
74  __COUT__ << "OPERATOR= COPY CONSTRUCTOR CANNOT BE USED - SO YOUR CODE IS WRONG! Crashing now." << std::endl;
75  __COUT__ << "OPERATOR= COPY CONSTRUCTOR CANNOT BE USED - SO YOUR CODE IS WRONG! Crashing now." << std::endl;
76  __COUT__ << "OPERATOR= COPY CONSTRUCTOR CANNOT BE USED - SO YOUR CODE IS WRONG! Crashing now." << std::endl;
77  __COUT__ << "OPERATOR= COPY CONSTRUCTOR CANNOT BE USED - SO YOUR CODE IS WRONG! Crashing now." << std::endl;
78  __COUT__ << "OPERATOR= COPY CONSTRUCTOR CANNOT BE USED - SO YOUR CODE IS WRONG! Crashing now." << std::endl;
79  __COUT__ << "OPERATOR= COPY CONSTRUCTOR CANNOT BE USED - SO YOUR CODE IS WRONG! Crashing now." << std::endl;
80  __COUT__ << "OPERATOR= COPY CONSTRUCTOR CANNOT BE USED - SO YOUR CODE IS WRONG! Crashing now." << std::endl;
81  exit(0);
82 
83  //copy to const members is not allowed.. but would look like this:
84 
85  configMgr_ = a.configMgr_;
86  configuration_ = a.configuration_;
87  //groupId_ = a.groupId_;
88  //linkColName_ = a.linkColName_;
89  //childLinkIndex_ = a.childLinkIndex_;
90  //row_ = a.row_;
91  //col_ = a.col_;
92  configView_ = a.configView_;
93  __COUT__ << "OPERATOR COPY CONSTRUCTOR" << std::endl;
94  return *this;
95  };
96 
97 
98  static const std::string DISCONNECTED_VALUE;
99  static const std::string VALUE_TYPE_DISCONNECTED;
100  static const std::string VALUE_TYPE_NODE;
101 
102  static const std::string NODE_TYPE_GROUP_TABLE;
103  static const std::string NODE_TYPE_TABLE;
104  static const std::string NODE_TYPE_GROUP_LINK;
105  static const std::string NODE_TYPE_UID_LINK;
106  static const std::string NODE_TYPE_VALUE;
107  static const std::string NODE_TYPE_UID;
108  static const std::string NODE_TYPE_ROOT;
109 
110  struct BitMap
111  {
112  BitMap():isDefault_(true), zero_(0) {}
113 
114  friend ConfigurationTree; //so ConfigurationTree can access private
115  const uint64_t& get (unsigned int row, unsigned int col) const { return isDefault_?zero_:bitmap_[row][col]; }
116  unsigned int numberOfRows () const { return bitmap_.size(); }
117  unsigned int numberOfColumns (unsigned int row) const { return bitmap_[row].size(); }
118 
119  private:
120  std::vector<std::vector<uint64_t>> bitmap_;
121  bool isDefault_; //when default always return 0
122  uint64_t zero_;
123  };
124 
125 
126 
127  //Methods
128 
129 
130  //==============================================================================
131  //getValue (not std::string value)
132  // throw exception unless it value node
133  template<class T>
134  void getValue(T& value) const
135  {
136  if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID) //this node is a value node
137  {
138  //attempt to interpret the value as a tree node path itself
139  try
140  {
141  ConfigurationTree valueAsTreeNode = getValueAsTreeNode();
142  //valueAsTreeNode.getValue<T>(value);
143  __COUT__ << "Success following path to tree node!" << std::endl;
144  //value has been interpreted as a tree node value
145  //now verify result under the rules of this column
146 // if(typeid(std::string) == typeid(value) ||
147 // typeid(std::basic_string<char>) == typeid(value))
148 // value = configView_->validateValueForColumn(
149 // valueAsTreeNode.getValueAsString(),col_);
150 // else
151  // value = (T)configView_->validateValueForColumn<T>(
152  // valueAsTreeNode.getValueAsString(),col_);
153  value = handleValidateValueForColumn(configView_,
154  valueAsTreeNode.getValueAsString(),col_,identity<T>());
155 
156  __COUT__ << "Successful value!" << std::endl;
157  return;
158  }
159  catch(...) //tree node path interpretation failed
160  {
161  //__COUT__ << "Invalid path, just returning normal value." << std::endl;
162  }
163 
164  //else normal return
165  configView_->getValue(value,row_,col_);
166  }
167  else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID) //this node is config node maybe with groupId
168  {
169  __SS__ << "Requesting getValue on config node level. Must be a value node." << std::endl;
170  __COUT_ERR__ << ss.str();
171  throw std::runtime_error(ss.str());
172  }
173  else if(row_ == ConfigurationView::INVALID)
174  {
175  __SS__ << "Malformed ConfigurationTree" << std::endl;
176  __COUT_ERR__ << ss.str();
177  throw std::runtime_error(ss.str());
178  }
179  else if(col_ == ConfigurationView::INVALID) //this node is uid node
180  {
181  __SS__ << "Requesting getValue on uid node level. Must be a value node." << std::endl;
182  __COUT_ERR__ << ss.str();
183  throw std::runtime_error(ss.str());
184  }
185  else
186  {
187  __SS__ << "Impossible" << std::endl;
188  __COUT_ERR__ << ss.str();
189  throw std::runtime_error(ss.str());
190  }
191  }
192  //special version of getValue for string type
193  // Note: necessary because types of std::basic_string<char> cause compiler problems if no string specific function
194  void getValue (std::string& value) const;
195  void getValueAsBitMap (ConfigurationTree::BitMap& value) const;
196 
197 
198  //==============================================================================
199  //getValue (not std::string value)
200  // throw exception unless it value node
201  template<class T>
202  T getValue(void) const
203  {
204  T value;
205  ConfigurationTree::getValue<T>(value);
206  return value;
207  }
208  //special version of getValue for string type
209  // Note: necessary because types of std::basic_string<char> cause compiler problems if no string specific function
210  std::string getValue (void) const;
211  ConfigurationTree::BitMap getValueAsBitMap (void) const;
212 
213 private:
214  template<typename T>
215  T handleValidateValueForColumn(const ConfigurationView* configView, std::string value, unsigned int col, ots::identity<T>) const
216  {
217  if(!configView)
218  {
219  __SS__ << "Null configView" << std::endl;
220  __COUT_ERR__ << ss.str();
221  throw std::runtime_error(ss.str());
222  }
223  std::cout << "210:::::" << "handleValidateValueForColumn<T>" << std::endl;
224  return configView->validateValueForColumn<T>(
225  value,col);
226  }
227 
228  std::string handleValidateValueForColumn(const ConfigurationView* configView, std::string value, unsigned int col, ots::identity<std::string>) const
229  {
230  if(!configView)
231  {
232  __SS__ << "Null configView" << std::endl;
233  __COUT_ERR__ << ss.str();
234  throw std::runtime_error(ss.str());
235  }
236  std::cout << "210:::::" << "handleValidateValueForColumn<string>" << std::endl;
237  return configView->validateValueForColumn(
238  value,col);
239  }
240 
241 public:
242 
243  //navigating between nodes
244  ConfigurationTree getNode (const std::string& nodeName, bool doNotThrowOnBrokenUIDLinks=false) const;
245  ConfigurationTree getBackNode ( std::string nodeName, unsigned int backSteps=1) const;
246  ConfigurationTree getForwardNode ( std::string nodeName, unsigned int forwardSteps=1) const;
247 
248 
249  //extracting information from node
250  const ConfigurationManager* getConfigurationManager (void) const { return configMgr_; }
251  const std::string& getConfigurationName (void) const;
252  const std::string& getFieldConfigurationName (void) const;
253  const ConfigurationVersion& getConfigurationVersion (void) const;
254  const time_t& getConfigurationCreationTime(void) const;
255  std::vector<std::string> getChildrenNames (bool byPriority = false) const;
256  std::vector<std::pair<std::string,ConfigurationTree> > getChildren (std::map<std::string /*relative-path*/, std::string /*value*/> filterMap = std::map<std::string /*relative-path*/, std::string /*value*/>(), bool byPriority = false) const;
257  std::map<std::string,ConfigurationTree> getChildrenMap (void) const;
258  std::string getEscapedValue (void) const;
259  const std::string& getValueAsString (bool returnLinkTableValue=false) const;
260  const std::string& getUIDAsString (void) const;
261  const std::string& getValueDataType (void) const;
262  const std::string& getValueType (void) const;
263  const std::string& getValueName (void) const;
264  std::string getNodeType (void) const;
265  const std::string& getDisconnectedTableName (void) const;
266  const std::string& getDisconnectedLinkID (void) const;
267  const std::string& getChildLinkIndex (void) const;
268  std::vector<std::string> getFixedChoices (void) const;
269 
270 public:
271 
272 
273  //boolean info
274  bool isDefaultValue (void) const;
275  bool isRootNode (void) const;
276  bool isConfigurationNode (void) const;
277  bool isValueNode (void) const;
278  bool isDisconnected (void) const;
279  bool isLinkNode (void) const;
280  bool isGroupLinkNode (void) const;
281  bool isUIDLinkNode (void) const;
282  bool isUIDNode (void) const;
283 
284 
285  void print (const unsigned int &depth = -1, std::ostream &out = std::cout) const;
286 
287  //make stream output easy
288  friend std::ostream& operator<< (std::ostream& out, const ConfigurationTree& t)
289  {
290  out << t.getValueAsString();
291  return out;
292  }
293 
294 protected:
295  const unsigned int& getRow (void) const;
296  const unsigned int& getColumn (void) const;
297  const unsigned int& getFieldRow (void) const;
298  const unsigned int& getFieldColumn (void) const;
299  const ViewColumnInfo& getColumnInfo (void) const;
300 
301  //extracting information from a list of records
302  struct RecordField
303  {
304  RecordField(const std::string &table, const std::string &uid,
305  const std::string &columnName, const std::string &relativePath,
306  const ViewColumnInfo *columnInfo)
307  :tableName_(table)
308  ,columnName_(columnName)
309  ,relativePath_(relativePath)
310  ,columnInfo_(columnInfo)
311  {}
312 
313  std::string tableName_, columnName_, relativePath_;
314  //relativePath_ is relative to record uid node, not including columnName_
315 
316  const ViewColumnInfo *columnInfo_;
317  };
318  std::vector<ConfigurationTree::RecordField> getCommonFields(const std::vector<std::string /*relative-path*/> &recordList, const std::vector<std::string /*relative-path*/> &fieldAcceptList, const std::vector<std::string /*relative-path*/> &fieldRejectList, unsigned int depth = -1) const;
319  std::set<std::string /*unique-value*/> getUniqueValuesForField(const std::vector<std::string /*relative-path*/> &recordList, const std::string &fieldName) const;
320 
321 private:
322  //privately ONLY allow full access to member variables through constructor
323  ConfigurationTree(const ConfigurationManager* const& configMgr, const ConfigurationBase* const& config, const std::string& groupId, const ConfigurationBase* const& linkParentConfig, const std::string &linkColName, const std::string &linkColValue, const unsigned int linkBackRow, const unsigned int linkBackCol, const std::string& disconnectedTargetName, const std::string& disconnectedLinkID, const std::string &childLinkIndex, const unsigned int row = ConfigurationView::INVALID, const unsigned int col = ConfigurationView::INVALID);
324 
325  static ConfigurationTree recurse (const ConfigurationTree& t, const std::string& childPath, bool doNotThrowOnBrokenUIDLinks);
326  static void recursivePrint(const ConfigurationTree& t, unsigned int depth, std::ostream &out, std::string space);
327  //static bool wildCardMatch (const std::string& needle, const std::string& haystack);
328 
329  void recursiveGetCommonFields(std::vector<ConfigurationTree::RecordField> &fieldCandidateList, std::vector<int> &fieldCount, const std::vector<std::string /*relative-path*/> &fieldAcceptList, const std::vector<std::string /*relative-path*/> &fieldRejectList, unsigned int depth, const std::string &relativePathBase, bool inFirstRecord) const;
330  ConfigurationTree getValueAsTreeNode (void) const;
331 
332  //Any given ConfigurationTree is either a config, uid, or value node:
333  // - config node is a pointer to a config table
334  // - uid node is a pointer to a row in a config table
335  // - value node is a pointer to a cell in a config table
336  //
337  //Assumption: uid column is present
338  const ConfigurationManager* configMgr_; //root node
339  const ConfigurationBase* configuration_; //config node
340  const std::string groupId_; //group config node
341  const ConfigurationBase* linkParentConfig_; //link node parent config pointer (could be used to traverse backwards through tree)
342  const std::string linkColName_; //link node field name
343  const std::string linkColValue_; //link node field value
344  const unsigned int linkBackRow_; //source table link row
345  const unsigned int linkBackCol_; //source table link col
346  const std::string disconnectedTargetName_; //only used if disconnected to determine target table name
347  const std::string disconnectedLinkID_; //only used if disconnected to determine target link ID
348  const std::string childLinkIndex_;//child link index
349  const unsigned int row_; //uid node
350  const unsigned int col_; //value node
351  const ConfigurationView* configView_;
352 
353 };
354 }
355 
356 #endif