ADTF  3.18.2
dd_access_map.h
Go to the documentation of this file.
1 
15 #ifndef DD_DD_ACCESS_MAP_H_INCLUDED
16 #define DD_DD_ACCESS_MAP_H_INCLUDED
17 
18 #include <ddl/dd/dd_error.h>
20 
21 #include <memory>
22 #include <unordered_map>
23 
24 namespace ddl {
25 namespace dd {
26 namespace utility {
27 
36  map_item_added,
37  map_item_removed,
38  map_item_changed,
39  map_item_renamed,
40  map_subitem_added,
41  map_subitem_removed,
42  map_subitem_changed,
43  map_subitem_renamed,
44  map_subitem_popped,
45  map_subitem_inserted
46 };
47 
54 template <typename T>
56 
63 template <typename T>
65 
72 template <typename DDL_TYPE_TO_ACCESS, typename TYPE_VALIDATOR_CLASS>
73 class TypeAccessMap : public TypeAccessMapObserver<DDL_TYPE_TO_ACCESS> {
74 public:
76  typedef DDL_TYPE_TO_ACCESS access_type;
78  typedef std::shared_ptr<DDL_TYPE_TO_ACCESS> value_type;
80  typedef std::unordered_map<std::string, value_type> container_type;
82  typedef typename container_type::iterator iterator;
84  typedef typename container_type::const_iterator const_iterator;
97 
98 public:
103  TypeAccessMap() = delete;
110  TypeAccessMap(TYPE_VALIDATOR_CLASS* validator, const std::string& validation_info)
111  : _validator(validator), _validation_info(validation_info)
112  {
113  }
118  virtual ~TypeAccessMap()
119  {
120  clear();
121  }
126  {
127  *this = std::move(other);
128  }
135  {
136  clear();
137  _validation_info = std::move(other._validation_info);
138  _types = std::move(other._types);
139  // the other will remove itself as observer with clear
140  for (const auto& current: _types) {
141  // the other will not observe this anymore
142  (static_cast<map_subject_type*>(current.second.get()))
143  ->detachObserver(static_cast<observer_type*>(&other));
144  // i want to observe this
145  (static_cast<map_subject_type*>(current.second.get()))
146  ->attachObserver(static_cast<observer_type*>(this));
147  }
148  _validator = nullptr;
149  return *this;
150  }
151 
158  : _validator(nullptr), _validation_info(other._validation_info)
159  {
160  for (auto current: other._types) {
161  auto new_type = std::make_shared<DDL_TYPE_TO_ACCESS>(*current.second);
162  // i want to observe this
163  (static_cast<map_subject_type*>(new_type.get()))
164  ->attachObserver(static_cast<observer_type*>(this));
165  _types[current.first] = new_type;
166  }
167  }
175  {
176  clear();
177  _validation_info = other._validation_info;
178  for (auto current: other._types) {
179  auto new_type = std::make_shared<DDL_TYPE_TO_ACCESS>(*current.second);
180  // i want to observe this
181  (static_cast<map_subject_type*>(new_type.get()))
182  ->attachObserver(static_cast<observer_type*>(this));
183  _types[current.first] = new_type;
184  }
185  _validator = nullptr;
186  return *this;
187  }
188 
189 public:
196  std::shared_ptr<const DDL_TYPE_TO_ACCESS> get(const std::string& type_name) const
197  {
198  auto it_find = _types.find(type_name);
199  if (it_find != _types.cend()) {
200  std::shared_ptr<const DDL_TYPE_TO_ACCESS> const_return = it_find->second;
201  return const_return;
202  }
203  return {};
204  }
212  bool contains(const std::string& type_name) const
213  {
214  const auto& it_find = _types.find(type_name);
215  if (it_find != _types.cend()) {
216  return true;
217  }
218  return false;
219  }
227  bool contains(const DDL_TYPE_TO_ACCESS& type_to_find) const
228  {
229  const auto& it_find = _types.find(type_to_find.getName());
230  if (it_find != _types.cend()) {
231  return type_to_find == *(it_find->second);
232  }
233  return false;
234  }
242  bool contains(const TypeAccessMap& other) const
243  {
244  for (const auto& other_content: other._types) {
245  if (!contains(*(other_content.second))) {
246  return false;
247  }
248  }
249  return true;
250  }
257  void add(const DDL_TYPE_TO_ACCESS& type_to_add)
258  {
259  const auto type_found = get(type_to_add.getName());
260  // have a look if the type already exists here
261  if (type_found) {
262  // check if they are equal
263  if (*type_found != type_to_add) {
264  throw ddl::dd::Error(_validation_info + "::add",
265  {type_to_add.getName()},
266  "value with the given name already exists");
267  }
268  return;
269  }
270  else {
271  // has already another type
272  bool already_exists = contains(type_to_add.getName());
273  if (_validator && !already_exists) {
274  already_exists = _validator->validateContains(type_to_add);
275  }
276  if (already_exists) {
277  throw ddl::dd::Error(_validation_info + "::add",
278  {type_to_add.getName()},
279  "value with the given name already exists");
280  }
281  }
282  auto new_type_value = std::make_shared<DDL_TYPE_TO_ACCESS>(type_to_add);
283  // i want to observe this
284  (static_cast<map_subject_type*>(new_type_value.get()))
285  ->attachObserver(static_cast<observer_type*>(this));
286  _types[type_to_add.getName()] = new_type_value;
287  if (_validator) {
288  _validator->notifyChangedMapContent(
289  TypeAccessMapEventCode::map_item_added, *new_type_value, type_to_add.getName());
290  }
291  }
292 
299  void emplace(DDL_TYPE_TO_ACCESS&& type_to_add)
300  {
301  const auto type_found = get(type_to_add.getName());
302  // have a look if the type already exists here
303  if (type_found) {
304  // check if they are equal
305  if (*type_found != type_to_add) {
306  throw ddl::dd::Error(_validation_info + "::add",
307  {type_to_add.getName()},
308  "value with the given name already exists");
309  }
310  }
311  else {
312  // has already another type
313  bool already_exists = contains(type_to_add.getName());
314  if (_validator && !already_exists) {
315  already_exists = _validator->validateContains(type_to_add);
316  }
317  if (already_exists) {
318  throw ddl::dd::Error(_validation_info + "::add",
319  {type_to_add.getName()},
320  "value with the given name already exists");
321  }
322  }
323  auto new_type_value = std::make_shared<DDL_TYPE_TO_ACCESS>(std::move(type_to_add));
324  // i want to observe this
325  (static_cast<map_subject_type*>(new_type_value.get()))
326  ->attachObserver(static_cast<observer_type*>(this));
327  _types[new_type_value->getName()] = new_type_value;
328  if (_validator) {
329  _validator->notifyChangedMapContent(
330  TypeAccessMapEventCode::map_item_added, *new_type_value, new_type_value->getName());
331  }
332  }
338  void remove(const std::string& type_name)
339  {
340  auto removed_value = access(type_name);
341  if (removed_value) {
342  _types.erase(type_name);
343  (static_cast<map_subject_type*>(removed_value.get()))
344  ->detachObserver(static_cast<observer_type*>(this));
345  if (_validator) {
346  _validator->notifyChangedMapContent(
347  TypeAccessMapEventCode::map_item_removed, *removed_value, type_name);
348  }
349  return;
350  }
351  throw ddl::dd::Error(
352  _validation_info + "::remove", {type_name}, "value with the given name does not exist");
353  }
360  std::shared_ptr<DDL_TYPE_TO_ACCESS> access(const std::string& type_name)
361  {
362  auto it_find = _types.find(type_name);
363  if (it_find != _types.end()) {
364  return it_find->second;
365  }
366  return {};
367  }
373  size_t getSize() const
374  {
375  return _types.size();
376  }
383  {
384  return _types.begin();
385  }
392  {
393  return _types.end();
394  }
401  {
402  return _types.cbegin();
403  }
410  {
411  return _types.cend();
412  }
419  {
420  return cbegin();
421  }
428  {
429  return cend();
430  }
438  bool operator==(const TypeAccessMap& other) const
439  {
440  if (getSize() != other.getSize()) {
441  return false;
442  }
443  else {
444  return contains(other);
445  }
446  }
454  bool operator!=(const TypeAccessMap& other) const
455  {
456  return !operator==(other);
457  }
462  void clear()
463  {
464  for (auto& current: _types) {
465  // unregister me as observer
466  (static_cast<map_subject_type*>(current.second.get()))
467  ->detachObserver(static_cast<observer_type*>(this));
468  }
469  _types.clear();
470  }
471 
472 public:
480  void modelChanged(event_code_type event_code,
481  subject_type& subject_changed,
482  const std::string& additional_info)
483  {
484  if (event_code == map_item_renamed) {
485  bool already_exists = contains(subject_changed.getName());
486  if (_validator && !already_exists) {
487  already_exists = _validator->validateContains(subject_changed);
488  }
489  if (already_exists) {
490  throw ddl::dd::Error(
491  _validation_info + "::modelChanged",
492  {subject_changed.getName()},
493  "Renaming not possible. Value with the given name already exists");
494  }
495  else {
496  // here additional info is the old name
497  iterator current = _types.find(additional_info);
498  // we need to readd it
499  auto value = current->second;
500  _types.erase(current);
501  _types[value->getName()] = value;
502  // after erasing do not touch the iterator anymore
503  }
504  }
505  if (_validator) {
506  // i should discover the shared_ptr here, but not needed at the moment .. so we try to
507  // get performance here
508  _validator->notifyChangedMapContent(event_code, subject_changed, additional_info);
509  }
510  }
511 
512 private:
521  void deepCopy(TypeAccessMap& destination, TYPE_VALIDATOR_CLASS* validator) const
522  {
523  destination = *this;
524  destination._validator = validator;
525  }
526  container_type _types;
527  TYPE_VALIDATOR_CLASS* _validator;
528  std::string _validation_info;
529 };
530 
531 } // namespace utility
532 } // namespace dd
533 } // namespace ddl
534 
535 #endif // DD_DD_ACCESS_MAP_H_INCLUDED
The ModelObserver utility template.
MODEL_SUBJECT_T subject_type
local definition of the subject code type
EVENT_CODE_T event_code_type
local definition of the event code type
Model Subject utility to define a Model Subject that notifies one or more observers.
Utility class for observable named items where the order is NOT important.
Definition: dd_access_map.h:73
void add(const DDL_TYPE_TO_ACCESS &type_to_add)
adds the given item
TypeAccessMapObserver< DDL_TYPE_TO_ACCESS > parent_type
local definition of the parent type to register observe
Definition: dd_access_map.h:86
TypeAccessMap()=delete
no default CTOR!
container_type::const_iterator const_iterator
local definition of the container const_iterator
Definition: dd_access_map.h:84
const_iterator begin() const
range based begin operator for const access
TypeAccessMapSubject< DDL_TYPE_TO_ACCESS > map_subject_type
local definition of the internal subject type
Definition: dd_access_map.h:88
const_iterator cbegin() const
const begin iterator access
container_type::iterator iterator
local definition of the container iterator
Definition: dd_access_map.h:82
TypeAccessMap & operator=(TypeAccessMap &&other)
move assignment operator
TypeAccessMap(TypeAccessMap &&other)
move CTOR
void remove(const std::string &type_name)
item to remove
void emplace(DDL_TYPE_TO_ACCESS &&type_to_add)
emplaces the given item
TypeAccessMap(const TypeAccessMap &other)
copies (deepcopy!) CTOR
bool contains(const std::string &type_name) const
determines is the type name exists in this map
void deepCopy(TypeAccessMap &destination, TYPE_VALIDATOR_CLASS *validator) const
copies the content of the of the list (by reseting the observer) and resets the validator to the give...
std::shared_ptr< DDL_TYPE_TO_ACCESS > value_type
local definition of the value type
Definition: dd_access_map.h:78
parent_type::event_code_type event_code_type
local definition of the eventcode type
Definition: dd_access_map.h:92
map_subject_type::observer_type observer_type
local definition of the observer type
Definition: dd_access_map.h:90
void modelChanged(event_code_type event_code, subject_type &subject_changed, const std::string &additional_info)
overrides the observers utility function.
TypeAccessMap & operator=(const TypeAccessMap &other)
copies (deepcopy!) and overwrite the current content.
const_iterator cend() const
const end iterator access
size_t getSize() const
Get the Size.
bool contains(const TypeAccessMap &other) const
determines if the other is a subset of this map
bool contains(const DDL_TYPE_TO_ACCESS &type_to_find) const
determines if the item is in this map.
DDL_TYPE_TO_ACCESS access_type
local definition of the access type
Definition: dd_access_map.h:76
std::shared_ptr< const DDL_TYPE_TO_ACCESS > get(const std::string &type_name) const
get the item with the given name type_name
friend TYPE_VALIDATOR_CLASS
friend validator class
Definition: dd_access_map.h:96
std::shared_ptr< DDL_TYPE_TO_ACCESS > access(const std::string &type_name)
change access to an item
void clear()
clears the list and remove this as observer
iterator end()
the range based end iterator
std::unordered_map< std::string, value_type > container_type
local definition of the container type
Definition: dd_access_map.h:80
const_iterator end() const
range based end operator for const access
parent_type::subject_type subject_type
local definition of the subject type
Definition: dd_access_map.h:94
iterator begin()
the range based begin iterator
bool operator!=(const TypeAccessMap &other) const
non equality operator.
TypeAccessMap(TYPE_VALIDATOR_CLASS *validator, const std::string &validation_info)
CTOR.
bool operator==(const TypeAccessMap &other) const
equality operator.
DataDefinition Model-Observer pattern utility.
OO DataDefinition Redesign.
TypeAccessMapEventCode
Internal event code to inform the parent DD Object about the change of an item within the list.
Definition: dd_access_map.h:35
@ validation_info
Validation Info.