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  @file Tree.hpp
34 
35  @author Jean-Christophe FABRE <jean-christophe.fabre@supagro.inra.fr>
36 */
37 
38 
39 #ifndef __OPENFLUID_CORE_TREE_HPP__
40 #define __OPENFLUID_CORE_TREE_HPP__
41 
42 #include <sstream>
43 #include <iostream>
44 #include <iomanip>
46 #include <openfluid/dllexport.hpp>
47 
48 
49 namespace openfluid { namespace core {
50 
51 
52 template<typename K, typename V>
54 {
55  public:
56 
57  typedef std::map<K,Tree<K,V>> Children_t;
58 
59  typedef typename Children_t::iterator iterator;
60 
61  typedef typename Children_t::const_iterator const_iterator;
62 
63 
64  protected:
65 
67 
68  Children_t m_Children;
69 
70  bool m_HasValue;
71 
72 
73  std::string keyToStr(const K& Key) const
74  {
75  std::ostringstream oss;
76 
77  if (!(oss << Key).fail())
78  return oss.str();
79  else
80  return "<unknown>";
81  }
82 
83 
84  public:
85 
86  /*
87  Default constructor
88  */
89  Tree<K,V>() : m_HasValue(false)
90  {
91 
92  }
93 
94 
95  // =====================================================================
96  // =====================================================================
97 
98  /**
99  Returns the value of the current tree node
100  @return the value associated to the node
101  @throw openfluid::base::FrameworkException if the node does not have a value
102  */
103  V getValue() const
104  {
105  if (m_HasValue)
106  return m_Value;
107  else
108  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Node has no value");
109 
110  }
111 
112 
113  // =====================================================================
114  // =====================================================================
115 
116  /**
117  Returns the value of the current tree node, or a default value if the node does not have a value
118  @param[in] DefaultVal the default value
119  @return the value associated to the node or the default value
120  */
121  V getValue(const V& DefaultVal) const
122  {
123  if (m_HasValue)
124  return m_Value;
125  else
126  return DefaultVal;
127  }
128 
129 
130  // =====================================================================
131  // =====================================================================
132 
133 
134  /**
135  Sets the value of the current tree node
136  @param[in] Val the value of the node
137  */
138  void setValue(const V& Val)
139  {
140  m_Value = Val;
141  m_HasValue = true;
142  }
143 
144 
145  // =====================================================================
146  // =====================================================================
147 
148 
149  /**
150  Returns true if the node has a value
151  @return true if the node has a value, false otherwise
152  */
153  bool hasValue() const
154  {
155  return m_HasValue;
156  }
157 
158 
159  // =====================================================================
160  // =====================================================================
161 
162 
163  /**
164  Returns a reference to the map of children of the current node
165  @return a map of children
166  */
167  Children_t& children()
168  {
169  return m_Children;
170  }
171 
172 
173  // =====================================================================
174  // =====================================================================
175 
176 
177  /**
178  Returns a const reference to the map of children of the current node
179  @return a map of children
180  */
181  const Children_t& children() const
182  {
183  return m_Children;
184  }
185 
186 
187  // =====================================================================
188  // =====================================================================
189 
190 
191  /**
192  Returns a reference to the child of the current node, identified by its key
193  @param[in] Key the key of the child node
194  @return the reference to the child node
195  @throw openfluid::base::FrameworkException if the child does not exist
196  */
197  Tree<K,V>& child(const K& Key)
198  {
199  auto it = m_Children.find(Key);
200 
201  if (it == m_Children.end())
202  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Key " + keyToStr(Key) + " does not exist");
203 
204  return (*it).second;
205  }
206 
207 
208  // =====================================================================
209  // =====================================================================
210 
211 
212  /**
213  Returns a const reference to the child of the current node, identified by its key
214  @param[in] Key the key of the child node
215  @return the reference to the child node
216  @throw openfluid::base::FrameworkException if the child does not exist
217  */
218  const Tree<K,V>& child(const K& Key) const
219  {
220  auto it = m_Children.find(Key);
221 
222  if (it == m_Children.end())
223  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Key " + keyToStr(Key) + " does not exist");
224 
225  return (*it).second;
226  }
227 
228 
229  // =====================================================================
230  // =====================================================================
231 
232 
233  /**
234  Returns the value of the child of the current node, identified by its key.
235  If the child node does not have a value, the given default value is returned
236  @param[in] Key the key of the child node
237  @param[in] DefaultVal the default value
238  @return the value of the child node or the default value
239  */
240  V getChildValue(const K& Key, const V& DefaultVal) const
241  {
242  auto it = m_Children.find(Key);
243 
244  if (it == m_Children.end())
245  return DefaultVal;
246 
247  return (*it).second.getValue(DefaultVal);
248  }
249 
250 
251  // =====================================================================
252  // =====================================================================
253 
254 
255  /**
256  Returns true if the current node has a child identified by the given key
257  @return true if the child node has been found, false otherwise
258  */
259  bool hasChild(const K& Key) const
260  {
261  return (m_Children.find(Key) != m_Children.end());
262  }
263 
264 
265  // =====================================================================
266  // =====================================================================
267 
268  /**
269  Adds a child to the current node, identified by its key and with the given value
270  @param[in] Key the key of the child node
271  @param[in] Val the value of the child node
272  @return the reference to the added child node
273  @throw openfluid::base::FrameworkException if the child already exists
274  */
275  Tree<K,V>& addChild(const K& Key, const V& Val)
276  {
277  if (hasChild(Key))
278  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Key " + keyToStr(Key) + " already exists");
279 
280  m_Children[Key] = Tree<K,V>();
281  m_Children[Key].setValue(Val);
282 
283  return m_Children[Key];
284  }
285 
286 
287  // =====================================================================
288  // =====================================================================
289 
290 
291  /**
292  Adds a child to the current node, identified by its key and with no value
293  @param[in] Key the key of the child node
294  @return the reference to the added child node
295  @throw openfluid::base::FrameworkException if the child already exists
296  */
297  Tree<K,V>& addChild(const K& Key)
298  {
299  if (hasChild(Key))
300  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Key " + keyToStr(Key) + " already exists");
301 
302  m_Children[Key] = Tree<K,V>();
303 
304  return m_Children[Key];
305  }
306 
307 
308  // =====================================================================
309  // =====================================================================
310 
311 
312  /**
313  Deletes a child of the current node, identified by its key and with no value
314  @param[in] Key the key of the child node to delete
315  */
316  void deleteChild(const K& Key)
317  {
318  auto it = m_Children.find(Key);
319 
320  if (it != m_Children.end())
321  m_Children.erase(it);
322  }
323 
324 
325  // =====================================================================
326  // =====================================================================
327 
328  /**
329  Returns an iterator referring to the first element of the children map
330  @return an iterator to the first element in the children map
331  */
332  inline iterator begin()
333  {
334  return m_Children.begin();
335  }
336 
337 
338  // =====================================================================
339  // =====================================================================
340 
341 
342  /**
343  Returns a const iterator referring to the first element of the children map
344  @return a const iterator to the first element in the children map
345  */
346  inline const_iterator begin() const
347  {
348  return m_Children.begin();
349  }
350 
351 
352  // =====================================================================
353  // =====================================================================
354 
355 
356  /**
357  Returns an iterator referring to the past-the-end element of the children map
358  @return an iterator to the past-the-end element of the children map
359  */
360  inline iterator end()
361  {
362  return m_Children.end();
363  }
364 
365 
366  // =====================================================================
367  // =====================================================================
368 
369 
370  /**
371  Returns a const iterator referring to the past-the-end element of the children map
372  @return a const iterator to the past-the-end element of the children map
373  */
374  inline const_iterator end() const
375  {
376  return m_Children.end();
377  }
378 
379 
380  // =====================================================================
381  // =====================================================================
382 
383 
384  /**
385  Clears the tree determined by the current node
386  */
387  void clear()
388  {
389  m_Value = V();
390 
391  for (auto& ChildNode : m_Children)
392  ChildNode.second.clear();
393 
394  m_Children.clear();
395  }
396 
397 
398  // =====================================================================
399  // =====================================================================
400 
401 
402  /**
403  Returns the size of the tree determined by the current node
404  @return the size of the tree
405  */
406  unsigned int size() const
407  {
408  int Size = 1;
409 
410  for (auto& ChildNode : m_Children)
411  Size += ChildNode.second.size();
412 
413  return Size;
414  }
415 
416 
417  // =====================================================================
418  // =====================================================================
419 
420 
421  /**
422  Writes hierarchically the tree determined by the current node into the given stream, using the given indentation
423  @param[in] OutStm the output stream to write into
424  @param[in] Indent the indent value for children nodes
425  */
426  void writeToStreamHierarchically(std::ostream& OutStm, unsigned int Indent = 0) const
427  {
428  for (auto& ChildNode : m_Children)
429  {
430  if (Indent)
431  OutStm << std::setw(Indent);
432 
433  OutStm << "[" << ChildNode.first;
434  if (ChildNode.second.hasValue())
435  OutStm << " -> " << ChildNode.second.getValue();
436  OutStm << "]\n";
437 
438  ChildNode.second.writeToStreamHierarchically(OutStm,Indent+4);
439  }
440  }
441 
442 
443  // =====================================================================
444  // =====================================================================
445 
446 
447  void writeToStreamFlat(std::ostream& OutStm) const
448  {
449  for (auto& ChildNode : m_Children)
450  {
451  OutStm << "{" << ChildNode.first;
452  if (ChildNode.second.hasValue())
453  OutStm << "(" << ChildNode.second.getValue() << ")";
454  ChildNode.second.writeToStreamFlat(OutStm);
455  OutStm << "}";
456  }
457  }
458 
459 };
460 
461 
462 } } // namespaces
463 
464 #endif /* __OPENFLUID_TREE_HPP__ */
Tree< K, V > & addChild(const K &Key, const V &Val)
Definition: Tree.hpp:275
std::map< K, Tree< K, V > > Children_t
Definition: Tree.hpp:57
iterator end()
Definition: Tree.hpp:360
Children_t & children()
Definition: Tree.hpp:167
const Tree< K, V > & child(const K &Key) const
Definition: Tree.hpp:218
void clear()
Definition: Tree.hpp:387
bool hasValue() const
Definition: Tree.hpp:153
void writeToStreamHierarchically(std::ostream &OutStm, unsigned int Indent=0) const
Definition: Tree.hpp:426
Tree< K, V > & addChild(const K &Key)
Definition: Tree.hpp:297
const_iterator begin() const
Definition: Tree.hpp:346
V getValue(const V &DefaultVal) const
Definition: Tree.hpp:121
V getValue() const
Definition: Tree.hpp:103
void deleteChild(const K &Key)
Definition: Tree.hpp:316
std::string keyToStr(const K &Key) const
Definition: Tree.hpp:73
Definition: FrameworkException.hpp:50
V m_Value
Definition: Tree.hpp:66
Children_t m_Children
Definition: Tree.hpp:68
unsigned int size() const
Definition: Tree.hpp:406
Tree< K, V > & child(const K &Key)
Definition: Tree.hpp:197
const Children_t & children() const
Definition: Tree.hpp:181
Definition: ApplicationException.hpp:47
iterator begin()
Definition: Tree.hpp:332
void setValue(const V &Val)
Definition: Tree.hpp:138
#define OPENFLUID_API
Definition: dllexport.hpp:87
const_iterator end() const
Definition: Tree.hpp:374
V getChildValue(const K &Key, const V &DefaultVal) const
Definition: Tree.hpp:240
Children_t::const_iterator const_iterator
Definition: Tree.hpp:61
bool m_HasValue
Definition: Tree.hpp:70
bool hasChild(const K &Key) const
Definition: Tree.hpp:259
void writeToStreamFlat(std::ostream &OutStm) const
Definition: Tree.hpp:447
Children_t::iterator iterator
Definition: Tree.hpp:59
Definition: Tree.hpp:53