commonlib
node.h
Go to the documentation of this file.
1 
11 #pragma once
12 #include <iterator>
13 #include <memory>
14 #include <sstream>
15 #include "type_converter.h"
16 
17 BEGIN_NAMESPACE_SERIALIZATION
18 
19 class Node;
20 using NodePtr = std::shared_ptr<Node>;
21 
26 class Node
27 {
28 public:
29 
30  virtual ~Node() = default;
31 
35  virtual void destroy() = 0;
36 
42  template <typename T>
43  void addAttribute(const std::string& name, const T& value);
44 
50  template <typename T>
51  void write(const std::string& name, const T& value);
52 
60  template <typename T, typename U>
61  void write(const std::string& name, const T& value, const U& defaultValue);
62 
68  template <typename T>
69  void read(const std::string& name, T& value);
70 
77  template <typename T, typename U>
78  void read(const std::string& name, T& value, const U& defaultValue);
79 
86  template <typename T>
87  void update(const std::string& name, T& value);
88 
95  template <typename T, typename U>
96  void update(const std::string& name, T& value, const U& defaultValue);
97 
103  virtual NodePtr updateChild(const std::string& childName) = 0;
104 
110  virtual NodePtr readChild(const std::string& childName) = 0;
111 
118  virtual NodePtr createNode(std::string name, std::string value) = 0;
119 
125  virtual void initializeNode(std::string name, std::string value) = 0;
126 
131  virtual void initializeNode(NodePtr node) = 0;
132 
137  virtual void setValue(std::string value) = 0;
138 
144  virtual NodePtr addChild(std::string name) = 0;
145 
151  virtual NodePtr addChild(const NodePtr& childNode) = 0;
152 
157  virtual NodePtr clone() = 0;
158 
164  NodePtr clone(const NodePtr& nodeToClone);
165 
171  virtual NodePtr addAttributeNode(const NodePtr& attributeNode) = 0;
172 
176  virtual void clearChildNodes() = 0;
177 
181  virtual void clearAttributeNodes() = 0;
182 
188  virtual NodePtr findChildNode(const std::string& name) = 0;
189 
195  virtual NodePtr findAttributeNode(const std::string& name) = 0;
196 
202  virtual NodePtr getAttribute(const size_t attributeIndex) = 0;
203 
209  virtual NodePtr getChild(const size_t childIndex) = 0;
210 
215  virtual size_t getAttributeCount() = 0;
216 
221  virtual size_t getChildCount() = 0;
222 
227  virtual void removeAttribute(const std::string& attributeName) = 0;
228 
233  virtual void removeAttribute(const size_t attributeIndex) = 0;
234 
239  virtual void removeAttribute(NodePtr& attributeNode) = 0;
240 
245  virtual void removeChild(const std::string& childName) = 0;
246 
251  virtual void removeChild(const size_t childIndex) = 0;
252 
257  virtual void removeChild(NodePtr& childNode) = 0;
258 
263  virtual std::string getName() = 0;
264 
269  virtual std::string getValue() = 0;
270 
275  virtual NodePtr getNextSibling() = 0;
276 
282  virtual void updateOperation(bool write) = 0;
283 
288  virtual bool isWrite() = 0;
289 
294  virtual bool isInitialized() = 0;
295 
300  virtual bool isEmpty() = 0;
301 
306  bool isDummy() const;
307 
308 
309 
310 protected:
311  virtual void internalWrite(const std::string& name, const std::string& value, const std::string& defaultValue) = 0;
312  virtual void internalRead(const std::string& name, std::string& value, const std::string& defaultValue) = 0;
313  virtual void internalAddAttribute(const std::string& name, const std::string& value) = 0;
314 
315  // Variable is set to true if node was created as a dummy node in an updateChild function when operation type was read and child was not found
316  bool isDummyNode = false;
317 
318 private:
319  const std::string defaultStringValue = "";
320 
321  // Variable is used when write is called without default value, so that written value and default value are always different and node is always created.
322  const std::string dummyString = "#";
323 
324  template <typename Iterator>
325  void writeIterable(const std::string& name, Iterator first, Iterator last);
326 
327  template <typename Iterator>
328  void readIterable(const std::string& name, Iterator first, Iterator last);
329 
330  template <typename OutputIterator>
331  void readIterable(const std::string& name, OutputIterator output);
332 
333  template <typename T>
334  typename std::enable_if<!is_container<T>::value>::type properTypeWrite(const std::string& name, const T& value)
335  {
336  const std::string valueString = TypeConverter<T>::toString(value);
337 
338  //Dummy string is added so that valueString and defaultValueString are always different and node is always created.
339  const std::string defaultValueString = valueString + this->dummyString;
340  internalWrite(name, valueString, defaultValueString);
341  }
342 
343  template <typename T>
344  typename std::enable_if<is_container<T>::value>::type properTypeWrite(const std::string& name, const T& value)
345  {
346  writeIterable(name, ContainerInputIterators<T>::begin(value), ContainerInputIterators<T>::end(value));
347  }
348 
349  template <typename T>
350  typename std::enable_if<!is_container<T>::value>::type properTypeRead(const std::string& name, T& value)
351  {
352  TypeConverter<T> defaultBaseTypeValue;
353  const std::string defaultValueString = TypeConverter<T>::toString(defaultBaseTypeValue.defaultValue);
354  std::string outputValueString;
355 
356  try
357  {
358  internalRead(name, outputValueString, defaultValueString);
359  value = static_cast<T>(TypeConverter<T>::convertStringToProperType(outputValueString));
360  }
361  catch (std::invalid_argument&)
362  {
363  throw XmlException(XmlExceptionCode::xecNodeDoesNotContainExpectedType);
364  }
365  catch (std::out_of_range&)
366  {
367  throw XmlException(XmlExceptionCode::xecValueIsOutOfRange);
368  }
369  }
370 
371  template <typename T>
372  typename std::enable_if<is_container<T>::value>::type properTypeRead(const std::string& name, T& value)
373  {
374  properContainerTypeRead(name, value);
375  }
376 
377  template <typename T>
378  typename std::enable_if<has_back_insert<T>::value>::type properContainerTypeRead(const std::string& name, T& value)
379  {
380  readIterable(name, std::back_insert_iterator<T>(value));
381  }
382 
383  template <typename T>
384  typename std::enable_if<!has_back_insert<T>::value>::type properContainerTypeRead(const std::string& name, T& value)
385  {
386  readIterable(name, ContainerOutputIterators<T>::begin(value), ContainerOutputIterators<T>::end(value));
387  }
388 
389  virtual NodePtr addUniqueChild(const std::string& name) = 0;
390 };
391 
392 template <typename T>
393 void Node::write(const std::string& name, const T& value)
394 {
395  properTypeWrite(name, value);
396 }
397 
398 template <typename T, typename U>
399 void Node::write(const std::string& name, const T& value, const U& defaultValue)
400 {
401  const std::string valueString = TypeConverter<T>::toString(value);
402  const std::string defaultValueString = TypeConverter<U>::toString(defaultValue);
403  internalWrite(name, valueString, defaultValueString);
404 }
405 
406 template <typename Iterator>
407 void Node::writeIterable(const std::string& name, Iterator first, Iterator last)
408 {
409  const size_t size = std::distance(first, last);
410  std::string inputValuesString;
411  using IteratorValueType = typename std::iterator_traits<Iterator>::value_type;
412 
413  for (size_t i = 0; i < size; i++)
414  {
415  inputValuesString += TypeConverter<IteratorValueType>::toString(*first);
416  inputValuesString += ";";
417  ++first;
418  }
419 
420  if (!inputValuesString.empty())
421  {
422  inputValuesString.pop_back();
423  }
424  internalWrite(name, inputValuesString, this->defaultStringValue);
425 }
426 
427 template <typename T>
428 void Node::read(const std::string& name, T& value)
429 {
430  properTypeRead(name, value);
431 }
432 
433 template <typename T, typename U>
434 void Node::read(const std::string& name, T& value, const U& defaultValue)
435 {
436  std::string outputValueString;
437  const std::string defaultValueString = TypeConverter<U>::toString(defaultValue);
438 
439  try
440  {
441  internalRead(name, outputValueString, defaultValueString);
442  value = static_cast<T>(TypeConverter<T>::convertStringToProperType(outputValueString));
443  }
444  catch (std::invalid_argument&)
445  {
446  throw XmlException(XmlExceptionCode::xecNodeDoesNotContainExpectedType);
447  }
448  catch (std::out_of_range&)
449  {
450  throw XmlException(XmlExceptionCode::xecValueIsOutOfRange);
451  }
452 }
453 
454 template <typename T>
455 void Node::update(const std::string& name, T& value)
456 {
457  if (isWrite())
458  {
459  write(name, value);
460  }
461  else
462  {
463  read(name, value);
464  }
465 }
466 
467 template <typename T, typename U>
468 void Node::update(const std::string& name, T& value, const U& defaultValue)
469 {
470  if (isWrite())
471  {
472  write(name, value, defaultValue);
473  }
474  else
475  {
476  read(name, value, defaultValue);
477  }
478 }
479 
480 template <typename Iterator>
481 void Node::readIterable(const std::string& name, Iterator first, Iterator last)
482 {
483  std::string outputValuesString;
484 
485  try
486  {
487  internalRead(name, outputValuesString, "");
488 
489  using IteratorValueType = typename std::iterator_traits<Iterator>::value_type;
490 
491  TypeConverter<IteratorValueType> defaultBaseTypeValue;
492  std::stringstream valuesStringStream(outputValuesString);
493  std::string stringSegment;
494 
495  const size_t size = std::distance(first, last);
496 
497  for (size_t i = 0; i < size; i++)
498  {
499  if (std::getline(valuesStringStream, stringSegment, ';'))
500  {
501  *first = static_cast<IteratorValueType>(TypeConverter<IteratorValueType>::convertStringToProperType(stringSegment));
502  }
503  else
504  {
505  *first = static_cast<IteratorValueType>(defaultBaseTypeValue.defaultValue);
506  }
507  ++first;
508  }
509  }
510  catch (std::invalid_argument&)
511  {
512  throw XmlException(XmlExceptionCode::xecNodeDoesNotContainExpectedType);
513  }
514  catch (std::out_of_range&)
515  {
516  throw XmlException(XmlExceptionCode::xecValueIsOutOfRange);
517  }
518 }
519 
520 
521 template <typename OutputIterator>
522 void Node::readIterable(const std::string& name, OutputIterator output)
523 {
524  std::string outputValuesString;
525  try
526  {
527  internalRead(name, outputValuesString, "");
528 
529  if (!outputValuesString.empty())
530  {
531  std::stringstream valuesStringStream(outputValuesString);
532  std::string stringSegment;
533 
534  while (std::getline(valuesStringStream, stringSegment, ';'))
535  {
536  *output++ = static_cast<typename output_iterator_traits<OutputIterator>::value_type>(
537  TypeConverter<typename output_iterator_traits<OutputIterator>::value_type>::convertStringToProperType(stringSegment));
538  }
539  }
540  }
541  catch (std::invalid_argument&)
542  {
543  throw XmlException(XmlExceptionCode::xecNodeDoesNotContainExpectedType);
544  }
545  catch (std::out_of_range&)
546  {
547  throw XmlException(XmlExceptionCode::xecValueIsOutOfRange);
548  }
549 }
550 
551 template <typename T>
552 void Node::addAttribute(const std::string& name, const T& value)
553 {
554  internalAddAttribute(name, TypeConverter<T>::toString(value));
555 }
556 
557 END_NAMESPACE_SERIALIZATION
virtual NodePtr addAttributeNode(const NodePtr &attributeNode)=0
addAttributeNode adds a given attribute node to a node and returns a pointer to it.
void addAttribute(const std::string &name, const T &value)
addAttribute function adds an attribute with a given name and given value to a node.
Definition: node.h:552
virtual NodePtr addChild(std::string name)=0
addChild function creates and adds a child with a given name to a node and returns a pointer to it...
virtual void setValue(std::string value)=0
setValue function sets a given value to a node.
Node is an abstract class that represents a node in an xml tree and defines functions for writing and...
Definition: node.h:26
virtual void removeAttribute(const std::string &attributeName)=0
removeAttribute removes all attributes with a given name from a node.
Definition: type_converter.h:256
virtual void initializeNode(std::string name, std::string value)=0
initializeNode function initializes an empty Node with a given name and given value.
void read(const std::string &name, T &value)
read function reads a value from a nodes child with a given name.
Definition: node.h:428
bool isDummy() const
isDummy returns true if node was created as a dummy node in updateChild function
virtual void clearChildNodes()=0
clearChildNodes clears all child nodes.
virtual NodePtr updateChild(const std::string &childName)=0
updateChild function creates or finds a node child with a given name based on update type ...
virtual bool isInitialized()=0
isInitialized returns true if node is initialized or false otherwise.
virtual NodePtr createNode(std::string name, std::string value)=0
createNode function creates a new Node and returns a pointer to it.
Definition: type_converter.h:273
virtual std::string getName()=0
getName returns a name of a node.
XmlException class that inherits from std::exception and is used for exception handling in xml serial...
Definition: xml_exception.h:42
void write(const std::string &name, const T &value)
write function creates a new child with a given name and adds a given value to it.
Definition: node.h:393
void update(const std::string &name, T &value)
update function writes or reads a value to/from a node, depends on nodes isWriteUpdateType ...
Definition: node.h:455
virtual bool isWrite()=0
isWrite returns true if node should be used for writting or false otherwise.
virtual size_t getAttributeCount()=0
getAttributeCount returns a number of attributes of a node.
virtual NodePtr getAttribute(const size_t attributeIndex)=0
getAttribute returns an attribute with a given index or nullptr if index is invalid.
virtual NodePtr getNextSibling()=0
getNextSibling returns a sibling of a node or nullptr if it doesnt exist.
virtual NodePtr findAttributeNode(const std::string &name)=0
findAttributeNode finds an attribute node with a given name and returns a pointer to it or nullptr if...
Definition: type_converter.h:89
virtual std::string getValue()=0
getValue returns a value of a node.
virtual void updateOperation(bool write)=0
updateOperation sets a node update operation (node can be used either for writting or reading)...
virtual void destroy()=0
destroy function releases internal node and sets it value to nullptr.
Structures for proper conversion between types that are used to build type generic write/read functio...
virtual void removeChild(const std::string &childName)=0
removeChild removes all children with a given name from a node.
virtual void clearAttributeNodes()=0
clearAttributeNodes clears all attribute nodes.
virtual size_t getChildCount()=0
getChildCount returns a number of children of a node.
Definition: type_converter.h:301
virtual NodePtr getChild(const size_t childIndex)=0
getChild returns a child with a given index or nullptr if index is invalid.
virtual NodePtr findChildNode(const std::string &name)=0
findChildNode finds a child node with a given name and returns a pointer to it or nullptr if not foun...
virtual NodePtr clone()=0
clone function creates a clone of a node.
virtual bool isEmpty()=0
isEmpty returns true if node does not have any children, attributes and if it does not have any value...
virtual NodePtr readChild(const std::string &childName)=0
readChild function finds a node child with a given name