otsdaq  v2_00_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 
111  //Methods
112 
113 
114  //==============================================================================
115  //getValue (not std::string value)
116  // throw exception unless it value node
117  template<class T>
118  void getValue(T& value) const
119  {
120  if(row_ != ConfigurationView::INVALID && col_ != ConfigurationView::INVALID) //this node is a value node
121  {
122  //attempt to interpret the value as a tree node path itself
123  try
124  {
125  ConfigurationTree valueAsTreeNode = getValueAsTreeNode();
126  //valueAsTreeNode.getValue<T>(value);
127  __COUT__ << "Success following path to tree node!" << std::endl;
128  //value has been interpreted as a tree node value
129  //now verify result under the rules of this column
130 // if(typeid(std::string) == typeid(value) ||
131 // typeid(std::basic_string<char>) == typeid(value))
132 // value = configView_->validateValueForColumn(
133 // valueAsTreeNode.getValueAsString(),col_);
134 // else
135  // value = (T)configView_->validateValueForColumn<T>(
136  // valueAsTreeNode.getValueAsString(),col_);
137  value = handleValidateValueForColumn(configView_,
138  valueAsTreeNode.getValueAsString(),col_,identity<T>());
139 
140  __COUT__ << "Successful value!" << std::endl;
141  return;
142  }
143  catch(...) //tree node path interpretation failed
144  {
145  //__COUT__ << "Invalid path, just returning normal value." << std::endl;
146  }
147 
148  //else normal return
149  configView_->getValue(value,row_,col_);
150  }
151  else if(row_ == ConfigurationView::INVALID && col_ == ConfigurationView::INVALID) //this node is config node maybe with groupId
152  {
153  __SS__ << "Requesting getValue on config node level. Must be a value node." << std::endl;
154  __COUT_ERR__ << ss.str();
155  throw std::runtime_error(ss.str());
156  }
157  else if(row_ == ConfigurationView::INVALID)
158  {
159  __SS__ << "Malformed ConfigurationTree" << std::endl;
160  __COUT_ERR__ << ss.str();
161  throw std::runtime_error(ss.str());
162  }
163  else if(col_ == ConfigurationView::INVALID) //this node is uid node
164  {
165  __SS__ << "Requesting getValue on uid node level. Must be a value node." << std::endl;
166  __COUT_ERR__ << ss.str();
167  throw std::runtime_error(ss.str());
168  }
169  else
170  {
171  __SS__ << "Impossible" << std::endl;
172  __COUT_ERR__ << ss.str();
173  throw std::runtime_error(ss.str());
174  }
175  }
176  //special version of getValue for string type
177  // Note: necessary because types of std::basic_string<char> cause compiler problems if no string specific function
178  void getValue (std::string& value) const;
179 
180 
181  //==============================================================================
182  //getValue (not std::string value)
183  // throw exception unless it value node
184  template<class T>
185  T getValue(void) const
186  {
187  T value;
188  ConfigurationTree::getValue<T>(value);
189  return value;
190  }
191  //special version of getValue for string type
192  // Note: necessary because types of std::basic_string<char> cause compiler problems if no string specific function
193  std::string getValue (void) const;
194 
195 private:
196  template<typename T>
197  T handleValidateValueForColumn(const ConfigurationView* configView, std::string value, unsigned int col, ots::identity<T>) const
198  {
199  if(!configView)
200  {
201  __SS__ << "Null configView" << std::endl;
202  __COUT_ERR__ << ss.str();
203  throw std::runtime_error(ss.str());
204  }
205  std::cout << "210:::::" << "handleValidateValueForColumn<T>" << std::endl;
206  return configView->validateValueForColumn<T>(
207  value,col);
208  }
209 
210  std::string handleValidateValueForColumn(const ConfigurationView* configView, std::string value, unsigned int col, ots::identity<std::string>) const
211  {
212  if(!configView)
213  {
214  __SS__ << "Null configView" << std::endl;
215  __COUT_ERR__ << ss.str();
216  throw std::runtime_error(ss.str());
217  }
218  std::cout << "210:::::" << "handleValidateValueForColumn<string>" << std::endl;
219  return configView->validateValueForColumn(
220  value,col);
221  }
222 
223 public:
224 
225  //navigating between nodes
226  ConfigurationTree getNode (const std::string& nodeName, bool doNotThrowOnBrokenUIDLinks=false) const;
227  ConfigurationTree getBackNode ( std::string nodeName, unsigned int backSteps=1) const;
228  ConfigurationTree getForwardNode ( std::string nodeName, unsigned int forwardSteps=1) const;
229 
230 
231  //extracting information from node
232  const ConfigurationManager* getConfigurationManager (void) const { return configMgr_; }
233  const std::string& getConfigurationName (void) const;
234  const std::string& getFieldConfigurationName (void) const;
235  const ConfigurationVersion& getConfigurationVersion (void) const;
236  const time_t& getConfigurationCreationTime(void) const;
237  std::vector<std::string> getChildrenNames (void) const;
238  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*/>()) const;
239  std::map<std::string,ConfigurationTree> getChildrenMap (void) const;
240  std::string getEscapedValue (void) const;
241  const std::string& getValueAsString (bool returnLinkTableValue=false) const;
242  const std::string& getUIDAsString (void) const;
243  const std::string& getValueDataType (void) const;
244  const std::string& getValueType (void) const;
245  const std::string& getValueName (void) const;
246  std::string getNodeType (void) const;
247  const std::string& getDisconnectedTableName (void) const;
248  const std::string& getDisconnectedLinkID (void) const;
249  const std::string& getChildLinkIndex (void) const;
250  std::vector<std::string> getFixedChoices (void) const;
251 
252 public:
253 
254 
255  //boolean info
256  bool isDefaultValue (void) const;
257  bool isRootNode (void) const;
258  bool isConfigurationNode (void) const;
259  bool isValueNode (void) const;
260  bool isDisconnected (void) const;
261  bool isLinkNode (void) const;
262  bool isGroupLinkNode (void) const;
263  bool isUIDLinkNode (void) const;
264  bool isUIDNode (void) const;
265 
266 
267  void print (const unsigned int &depth = -1, std::ostream &out = std::cout) const;
268 
269  //make stream output easy
270  friend std::ostream& operator<< (std::ostream& out, const ConfigurationTree& t)
271  {
272  out << t.getValueAsString();
273  return out;
274  }
275 
276 protected:
277  const unsigned int& getRow (void) const;
278  const unsigned int& getColumn (void) const;
279  const unsigned int& getFieldRow (void) const;
280  const unsigned int& getFieldColumn (void) const;
281  const ViewColumnInfo& getColumnInfo (void) const;
282 
283  //extracting information from a list of records
284  struct RecordField
285  {
286  RecordField(const std::string &table, const std::string &uid,
287  const std::string &columnName, const std::string &relativePath,
288  const ViewColumnInfo *columnInfo)
289  :tableName_(table)
290  ,columnName_(columnName)
291  ,relativePath_(relativePath)
292  ,columnInfo_(columnInfo)
293  {}
294 
295  std::string tableName_, columnName_, relativePath_;
296  //relativePath_ is relative to record uid node, not including columnName_
297 
298  const ViewColumnInfo *columnInfo_;
299  };
300  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;
301  std::set<std::string /*unique-value*/> getUniqueValuesForField(const std::vector<std::string /*relative-path*/> &recordList, const std::string &fieldName) const;
302 
303 private:
304  //privately ONLY allow full access to member variables through constructor
305  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);
306 
307  static ConfigurationTree recurse (const ConfigurationTree& t, const std::string& childPath, bool doNotThrowOnBrokenUIDLinks);
308  static void recursivePrint(const ConfigurationTree& t, unsigned int depth, std::ostream &out, std::string space);
309  static bool wildCardMatch (const std::string& needle, const std::string& haystack);
310 
311  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;
312  ConfigurationTree getValueAsTreeNode (void) const;
313 
314  //Any given ConfigurationTree is either a config, uid, or value node:
315  // - config node is a pointer to a config table
316  // - uid node is a pointer to a row in a config table
317  // - value node is a pointer to a cell in a config table
318  //
319  //Assumption: uid column is present
320  const ConfigurationManager* configMgr_; //root node
321  const ConfigurationBase* configuration_; //config node
322  const std::string groupId_; //group config node
323  const ConfigurationBase* linkParentConfig_; //link node parent config pointer (could be used to traverse backwards through tree)
324  const std::string linkColName_; //link node field name
325  const std::string linkColValue_; //link node field value
326  const unsigned int linkBackRow_; //source table link row
327  const unsigned int linkBackCol_; //source table link col
328  const std::string disconnectedTargetName_; //only used if disconnected to determine target table name
329  const std::string disconnectedLinkID_; //only used if disconnected to determine target link ID
330  const std::string childLinkIndex_;//child link index
331  const unsigned int row_; //uid node
332  const unsigned int col_; //value node
333  const ConfigurationView* configView_;
334 
335 };
336 }
337 
338 #endif