Documentation for OpenFLUID 2.2.0
Tree.hpp
Go to the documentation of this file.
1 /*
2 
3  This file is part of OpenFLUID software
4  Copyright(c) 2007, INRA - Montpellier SupAgro
5 
6 
7  == GNU General Public License Usage ==
8 
9  OpenFLUID is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  OpenFLUID is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with OpenFLUID. If not, see <http://www.gnu.org/licenses/>.
21 
22 
23  == Other Usage ==
24 
25  Other Usage means a use of OpenFLUID that is inconsistent with the GPL
26  license, and requires a written agreement between You and INRA.
27  Licensees for Other Usage of OpenFLUID may use this file in accordance
28  with the terms contained in the written agreement between You and INRA.
29 
30 */
31 
32 
33 /**
34  @file Tree.hpp
35 
36  @author Jean-Christophe FABRE <jean-christophe.fabre@inra.fr>
37 */
38 
39 
40 #ifndef __OPENFLUID_CORE_TREE_HPP__
41 #define __OPENFLUID_CORE_TREE_HPP__
42 
43 
44 #include <sstream>
45 #include <iostream>
46 #include <iomanip>
48 #include <openfluid/dllexport.hpp>
49 
50 
51 namespace openfluid { namespace core {
52 
53 
54 template<typename K, typename V>
56 {
57  public:
58 
59  typedef std::map<K,Tree<K,V>> Children_t;
60 
61  typedef typename Children_t::iterator iterator;
62 
63  typedef typename Children_t::const_iterator const_iterator;
64 
65 
66  protected:
67 
69 
71 
72  bool m_HasValue;
73 
74 
75  std::string keyToStr(const K& Key) const
76  {
77  std::ostringstream oss;
78 
79  if (!(oss << Key).fail())
80  {
81  return oss.str();
82  }
83  else
84  {
85  return "<unknown>";
86  }
87  }
88 
89 
90  public:
91 
92  /*
93  Default constructor
94  */
95  Tree<K,V>() : m_HasValue(false)
96  { }
97 
98 
99  // =====================================================================
100  // =====================================================================
101 
102 
103  /**
104  Returns the value of the current tree node
105  @return the value associated to the node
106  @throw openfluid::base::FrameworkException if the node does not have a value
107  */
108  V getValue() const
109  {
110  if (m_HasValue)
111  {
112  return m_Value;
113  }
114  else
115  {
116  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Node has no value");
117  }
118  }
119 
120 
121  // =====================================================================
122  // =====================================================================
123 
124 
125  /**
126  Returns the value of the current tree node, or a default value if the node does not have a value
127  @param[in] DefaultVal the default value
128  @return the value associated to the node or the default value
129  */
130  V getValue(const V& DefaultVal) const
131  {
132  if (m_HasValue)
133  {
134  return m_Value;
135  }
136  else
137  {
138  return DefaultVal;
139  }
140  }
141 
142 
143  // =====================================================================
144  // =====================================================================
145 
146 
147  /**
148  Sets the value of the current tree node
149  @param[in] Val the value of the node
150  */
151  void setValue(const V& Val)
152  {
153  m_Value = Val;
154  m_HasValue = true;
155  }
156 
157 
158  // =====================================================================
159  // =====================================================================
160 
161 
162  /**
163  Returns true if the node has a value
164  @return true if the node has a value, false otherwise
165  */
166  bool hasValue() const
167  {
168  return m_HasValue;
169  }
170 
171 
172  // =====================================================================
173  // =====================================================================
174 
175 
176  /**
177  Returns a reference to the map of children of the current node
178  @return a map of children
179  */
181  {
182  return m_Children;
183  }
184 
185 
186  // =====================================================================
187  // =====================================================================
188 
189 
190  /**
191  Returns a const reference to the map of children of the current node
192  @return a map of children
193  */
194  const Children_t& children() const
195  {
196  return m_Children;
197  }
198 
199 
200  // =====================================================================
201  // =====================================================================
202 
203 
204  /**
205  Returns a reference to the child of the current node, identified by its key
206  @param[in] Key the key of the child node
207  @return the reference to the child node
208  @throw openfluid::base::FrameworkException if the child does not exist
209  */
210  Tree<K,V>& child(const K& Key)
211  {
212  auto it = m_Children.find(Key);
213 
214  if (it == m_Children.end())
215  {
216  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Key " + keyToStr(Key) + " does not exist");
217  }
218 
219  return (*it).second;
220  }
221 
222 
223  // =====================================================================
224  // =====================================================================
225 
226 
227  /**
228  Returns a const reference to the child of the current node, identified by its key
229  @param[in] Key the key of the child node
230  @return the reference to the child node
231  @throw openfluid::base::FrameworkException if the child does not exist
232  */
233  const Tree<K,V>& child(const K& Key) const
234  {
235  auto it = m_Children.find(Key);
236 
237  if (it == m_Children.end())
238  {
239  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Key " + keyToStr(Key) + " does not exist");
240  }
241 
242  return (*it).second;
243  }
244 
245 
246  // =====================================================================
247  // =====================================================================
248 
249 
250  /**
251  Returns the value of the child of the current node, identified by its key.
252  If the child node does not have a value, the given default value is returned
253  @param[in] Key the key of the child node
254  @param[in] DefaultVal the default value
255  @return the value of the child node or the default value
256  */
257  V getChildValue(const K& Key, const V& DefaultVal) const
258  {
259  auto it = m_Children.find(Key);
260 
261  if (it == m_Children.end())
262  {
263  return DefaultVal;
264  }
265 
266  return (*it).second.getValue(DefaultVal);
267  }
268 
269 
270  // =====================================================================
271  // =====================================================================
272 
273 
274  /**
275  Returns true if the current node has a child identified by the given key
276  @return true if the child node has been found, false otherwise
277  */
278  bool hasChild(const K& Key) const
279  {
280  return (m_Children.find(Key) != m_Children.end());
281  }
282 
283 
284  // =====================================================================
285  // =====================================================================
286 
287 
288  /**
289  Adds a child to the current node, identified by its key and with the given value
290  @param[in] Key the key of the child node
291  @param[in] Val the value of the child node
292  @return the reference to the added child node
293  @throw openfluid::base::FrameworkException if the child already exists
294  */
295  Tree<K,V>& addChild(const K& Key, const V& Val)
296  {
297  if (hasChild(Key))
298  {
299  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Key " + keyToStr(Key) + " already exists");
300  }
301 
302  m_Children[Key] = Tree<K,V>();
303  m_Children[Key].setValue(Val);
304 
305  return m_Children[Key];
306  }
307 
308 
309  // =====================================================================
310  // =====================================================================
311 
312 
313  /**
314  Adds a child to the current node, identified by its key and with no value
315  @param[in] Key the key of the child node
316  @return the reference to the added child node
317  @throw openfluid::base::FrameworkException if the child already exists
318  */
319  Tree<K,V>& addChild(const K& Key)
320  {
321  if (hasChild(Key))
322  {
323  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Key " + keyToStr(Key) + " already exists");
324  }
325 
326  m_Children[Key] = Tree<K,V>();
327 
328  return m_Children[Key];
329  }
330 
331 
332  // =====================================================================
333  // =====================================================================
334 
335 
336  /**
337  Deletes a child of the current node, identified by its key and with no value
338  @param[in] Key the key of the child node to delete
339  */
340  void deleteChild(const K& Key)
341  {
342  auto it = m_Children.find(Key);
343 
344  if (it != m_Children.end())
345  {
346  m_Children.erase(it);
347  }
348  }
349 
350 
351  // =====================================================================
352  // =====================================================================
353 
354 
355  /**
356  Returns an iterator referring to the first element of the children map
357  @return an iterator to the first element in the children map
358  */
359  inline iterator begin()
360  {
361  return m_Children.begin();
362  }
363 
364 
365  // =====================================================================
366  // =====================================================================
367 
368 
369  /**
370  Returns a const iterator referring to the first element of the children map
371  @return a const iterator to the first element in the children map
372  */
373  inline const_iterator begin() const
374  {
375  return m_Children.begin();
376  }
377 
378 
379  // =====================================================================
380  // =====================================================================
381 
382 
383  /**
384  Returns an iterator referring to the past-the-end element of the children map
385  @return an iterator to the past-the-end element of the children map
386  */
387  inline iterator end()
388  {
389  return m_Children.end();
390  }
391 
392 
393  // =====================================================================
394  // =====================================================================
395 
396 
397  /**
398  Returns a const iterator referring to the past-the-end element of the children map
399  @return a const iterator to the past-the-end element of the children map
400  */
401  inline const_iterator end() const
402  {
403  return m_Children.end();
404  }
405 
406 
407  // =====================================================================
408  // =====================================================================
409 
410 
411  /**
412  Clears the tree determined by the current node
413  */
414  void clear()
415  {
416  m_Value = V();
417 
418  for (auto& ChildNode : m_Children)
419  {
420  ChildNode.second.clear();
421  }
422 
423  m_Children.clear();
424  }
425 
426 
427  // =====================================================================
428  // =====================================================================
429 
430 
431  /**
432  Returns the size of the tree determined by the current node
433  @return the size of the tree
434  */
435  unsigned int size() const
436  {
437  int Size = 1;
438 
439  for (auto& ChildNode : m_Children)
440  {
441  Size += ChildNode.second.size();
442  }
443 
444  return Size;
445  }
446 
447 
448  // =====================================================================
449  // =====================================================================
450 
451 
452  /**
453  Writes hierarchically the tree determined by the current node into the given stream, using the given indentation
454  @param[in] OutStm the output stream to write into
455  @param[in] Indent the indent value for children nodes
456  */
457  void writeToStreamHierarchically(std::ostream& OutStm, unsigned int Indent = 0) const
458  {
459  for (auto& ChildNode : m_Children)
460  {
461  if (Indent)
462  {
463  OutStm << std::setw(Indent);
464  }
465 
466  OutStm << "[" << ChildNode.first;
467  if (ChildNode.second.hasValue())
468  {
469  OutStm << " -> " << ChildNode.second.getValue();
470  }
471  OutStm << "]\n";
472 
473  ChildNode.second.writeToStreamHierarchically(OutStm,Indent+4);
474  }
475  }
476 
477 
478  // =====================================================================
479  // =====================================================================
480 
481 
482  void writeToStreamFlat(std::ostream& OutStm) const
483  {
484  for (auto& ChildNode : m_Children)
485  {
486  OutStm << "{" << ChildNode.first;
487  if (ChildNode.second.hasValue())
488  {
489  OutStm << "(" << ChildNode.second.getValue() << ")";
490  }
491  ChildNode.second.writeToStreamFlat(OutStm);
492  OutStm << "}";
493  }
494  }
495 
496 };
497 
498 
499 } } // namespaces
500 
501 #endif /* __OPENFLUID_CORE_TREE_HPP__ */
Definition: FrameworkException.hpp:51
Definition: Tree.hpp:56
std::string keyToStr(const K &Key) const
Definition: Tree.hpp:75
void deleteChild(const K &Key)
Definition: Tree.hpp:340
void setValue(const V &Val)
Definition: Tree.hpp:151
void writeToStreamHierarchically(std::ostream &OutStm, unsigned int Indent=0) const
Definition: Tree.hpp:457
unsigned int size() const
Definition: Tree.hpp:435
void clear()
Definition: Tree.hpp:414
V getChildValue(const K &Key, const V &DefaultVal) const
Definition: Tree.hpp:257
bool m_HasValue
Definition: Tree.hpp:72
const Children_t & children() const
Definition: Tree.hpp:194
Tree< K, V > & addChild(const K &Key)
Definition: Tree.hpp:319
V getValue() const
Definition: Tree.hpp:108
Children_t::iterator iterator
Definition: Tree.hpp:61
bool hasValue() const
Definition: Tree.hpp:166
Children_t m_Children
Definition: Tree.hpp:70
Children_t & children()
Definition: Tree.hpp:180
V m_Value
Definition: Tree.hpp:68
V getValue(const V &DefaultVal) const
Definition: Tree.hpp:130
void writeToStreamFlat(std::ostream &OutStm) const
Definition: Tree.hpp:482
const Tree< K, V > & child(const K &Key) const
Definition: Tree.hpp:233
const_iterator end() const
Definition: Tree.hpp:401
Tree< K, V > & addChild(const K &Key, const V &Val)
Definition: Tree.hpp:295
iterator end()
Definition: Tree.hpp:387
const_iterator begin() const
Definition: Tree.hpp:373
bool hasChild(const K &Key) const
Definition: Tree.hpp:278
iterator begin()
Definition: Tree.hpp:359
Children_t::const_iterator const_iterator
Definition: Tree.hpp:63
Tree< K, V > & child(const K &Key)
Definition: Tree.hpp:210
std::map< K, Tree< K, V > > Children_t
Definition: Tree.hpp:59
#define OPENFLUID_API
Definition: dllexport.hpp:86
Definition: ApplicationException.hpp:47