Dev Essential
Loading...
Searching...
No Matches
access_list.h
Go to the documentation of this file.
1
14
15#ifndef DDL_UTILITY_ACCESS_LIST_H_INCLUDED
16#define DDL_UTILITY_ACCESS_LIST_H_INCLUDED
17
22
23#include <algorithm>
24#include <memory>
25#include <unordered_map>
26#include <string_view>
27
28namespace ddl {
29namespace utility {
30 // forward declaration
31 template <typename DDL_TYPE_TO_ACCESS, typename TYPE_VALIDATOR_CLASS>
32 class TypeAccessList;
33}
34namespace dd {
35namespace utility {
44 list_item_added,
45 list_item_removed,
46 list_item_changed,
47 list_item_renamed,
48 list_subitem_added,
49 list_subitem_removed,
50 list_subitem_changed,
51 list_item_popped,
52 list_subitem_popped,
53 list_item_inserted,
54 list_subitem_inserted,
55 list_subitem_renamed,
56 list_item_removing,
57 list_subitem_removing,
58 list_item_renaming,
59 list_subitem_renaming
60};
61
68template <typename T>
70
77template <typename T>
79
86template <typename DDL_TYPE_TO_ACCESS, typename TYPE_VALIDATOR_CLASS>
87class TypeAccessList : public TypeAccessListObserver<DDL_TYPE_TO_ACCESS> {
88public:
90 typedef DDL_TYPE_TO_ACCESS access_type;
92 typedef std::shared_ptr<DDL_TYPE_TO_ACCESS> value_type;
94 typedef std::vector<value_type> container_type;
96 typedef std::unordered_map<std::string_view, value_type> container_named_type;
98 typedef typename container_type::iterator iterator;
100 typedef typename container_type::const_iterator const_iterator;
113
114public:
119 TypeAccessList() = delete;
127 : _validator(validator), _validation_info(validation_info)
128 {
129 }
130
135 {
136 clear();
137 }
138
142 {
143 *this = std::move(other);
144 }
145
151 {
152 clear();
153 _validation_info = std::move(other._validation_info);
154 _types = std::move(other._types);
155 // the other will not observe this anymore after this clear
156 for (const auto& current: _types) {
157 // the other will not observe this anymore
158 (static_cast<map_subject_type*>(current.get()))
159 ->detachObserver(static_cast<observer_type*>(&other));
160 // i want to observe this
161 (static_cast<map_subject_type*>(current.get()))
162 ->attachObserver(static_cast<observer_type*>(this));
163 }
164 return *this;
165 }
166
173 : _validator(nullptr), _validation_info(other._validation_info)
174 {
175 for (auto current: other._types) {
176 auto new_type = std::make_shared<DDL_TYPE_TO_ACCESS>(*current);
177 // i want to observe this
178 (static_cast<map_subject_type*>(new_type.get()))
179 ->attachObserver(static_cast<observer_type*>(this));
180 _types.push_back(new_type);
181 }
182 }
183
190 {
191 clear();
192 _validation_info = other._validation_info;
193 for (auto current: other._types) {
194 auto new_type = std::make_shared<DDL_TYPE_TO_ACCESS>(*current);
195 // i want to observe this
196 (static_cast<map_subject_type*>(new_type.get()))
197 ->attachObserver(static_cast<observer_type*>(this));
198 _types.push_back(new_type);
199 }
200 _validator = nullptr;
201 return *this;
202 }
203
204public:
211 std::shared_ptr<const DDL_TYPE_TO_ACCESS> get(std::string_view type_name) const
212 {
213 if (_validator) {
214 const auto named_items = getNamedContainer();
215 const auto found = named_items->find(type_name);
216 if (found != named_items->end()) {
217 return found->second;
218 }
219 }
220 else {
221 for (auto& current: _types) {
222 if (current->getName() == type_name) {
223 std::shared_ptr<const DDL_TYPE_TO_ACCESS> const_return = current;
224 return const_return;
225 }
226 }
227 }
228 return {};
229 }
230
238 Optional<size_t> getPosOf(const std::string& type_name) const
239 {
240 size_t current_pos = 0;
241 for (auto& current: _types) {
242 if (current->getName() == type_name) {
243 return current_pos;
244 }
245 ++current_pos;
246 }
247
248 return {};
249 }
250
258 bool contains(const std::string& type_name) const
259 {
260 if (_validator) {
261 const auto named_items = getNamedContainer();
262 const auto found = named_items->find(type_name);
263 if (found != named_items->end()) {
264 return true;
265 }
266 }
267 else {
268 for (auto& current: _types) {
269 if (current->getName() == type_name) {
270 return true;
271 }
272 }
273 }
274 return false;
275 }
276
284 bool contains(const DDL_TYPE_TO_ACCESS& type_to_find) const
285 {
286 const auto value_found = get(type_to_find.getName());
287 if (value_found) {
288 return type_to_find == *value_found;
289 }
290 return false;
291 }
292
300 bool contains(const TypeAccessList& other) const
301 {
302 for (const auto& other_content: other._types) {
303 if (!contains(*other_content)) {
304 return false;
305 }
306 }
307 return true;
308 }
309
317 std::shared_ptr<DDL_TYPE_TO_ACCESS> create(const DDL_TYPE_TO_ACCESS& type_to_add)
318 {
319 if (checkExistenceAndEquality(type_to_add)) {
320 // this will immediatelly return if the type exists and is equal
321 // otherwise the check will throw!
322 return access(type_to_add.getName());
323 }
324
325 auto new_type_value = std::make_shared<DDL_TYPE_TO_ACCESS>(type_to_add);
326 // i want to observe this
327 (static_cast<map_subject_type*>(new_type_value.get()))
328 ->attachObserver(static_cast<observer_type*>(this));
329 _types.push_back(new_type_value);
330 if (_validator) {
331 const auto named_items = getNamedContainer();
332 (*named_items)[new_type_value->getName()] = new_type_value;
333 }
334 if (_validator) {
335 _validator->notifyChangedListContent(
336 TypeAccessListEventCode::list_item_added, *new_type_value, type_to_add.getName());
337 }
338 return new_type_value;
339 }
340
347 void add(const DDL_TYPE_TO_ACCESS& type_to_add)
348 {
349 create(type_to_add);
350 }
351
360 void insert(const size_t pos_idx, const DDL_TYPE_TO_ACCESS& type_to_add)
361 {
362 if (pos_idx > getSize()) {
363 throw ddl::dd::Error(
364 _validation_info + "::insert", {type_to_add.getName()}, "given pos_idx is invalid");
365 }
366 else if (pos_idx == getSize()) {
367 add(type_to_add);
368 }
369 else {
370 if (checkExistenceAndEquality(type_to_add)) {
371 // this will immediatelly return if the type exists and is equal
372 // otherwise the check will throw!
373 return;
374 }
375 auto new_type_value = std::make_shared<DDL_TYPE_TO_ACCESS>(type_to_add);
376 // i want to observe this
377 (static_cast<map_subject_type*>(new_type_value.get()))
378 ->attachObserver(static_cast<observer_type*>(this));
379
380 auto cit = cbegin();
381 std::advance(cit, pos_idx);
382 _types.insert(cit, new_type_value);
383 if (_validator) {
384 const auto named_items = getNamedContainer();
385 (*named_items)[new_type_value->getName()] = new_type_value;
386 }
387 if (_validator) {
388 _validator->notifyChangedListContent(TypeAccessListEventCode::list_item_inserted,
389 *new_type_value,
390 type_to_add.getName());
391 }
392 }
393 }
394
402 std::shared_ptr<DDL_TYPE_TO_ACCESS> create(DDL_TYPE_TO_ACCESS&& type_to_add)
403 {
404 if (checkExistenceAndEquality(type_to_add)) {
405 // this will immediatelly return if the type exists and is equal
406 // otherwise the check will throw!
407 return access(type_to_add.getName());
408 }
409 auto new_type_value = std::make_shared<DDL_TYPE_TO_ACCESS>(std::move(type_to_add));
410 // i want to observe this
411 (static_cast<map_subject_type*>(new_type_value.get()))
412 ->attachObserver(static_cast<observer_type*>(this));
413 _types.push_back(new_type_value);
414 if (_validator) {
415 const auto named_items = getNamedContainer();
416 (*named_items)[new_type_value->getName()] = new_type_value;
417 }
418 if (_validator) {
419 _validator->notifyChangedListContent(TypeAccessListEventCode::list_item_added,
420 *new_type_value,
421 new_type_value->getName());
422 }
423 return new_type_value;
424 }
425
432 void emplace(DDL_TYPE_TO_ACCESS&& type_to_add)
433 {
434 create(std::move(type_to_add));
435 }
436
442 void remove(const std::string& type_name)
443 {
444 value_type removed_value;
445 typename container_type::iterator current_it;
446 for (current_it = _types.begin(); current_it != _types.end(); ++current_it) {
447 if ((*current_it)->getName() == type_name) {
448 removed_value = (*current_it);
449 break;
450 }
451 }
452 if (removed_value) {
453 if (_validator) {
454 _validator->notifyChangedListContent(
455 TypeAccessListEventCode::list_item_removing, *removed_value, type_name);
456 }
457 _types.erase(current_it);
458 if (_validator) {
459 const auto named_items = getNamedContainer();
460 named_items->erase(type_name);
461 }
462 (static_cast<subject_type*>(removed_value.get()))
463 ->detachObserver(static_cast<observer_type*>(this));
464 if (_validator) {
465 _validator->notifyChangedListContent(
466 TypeAccessListEventCode::list_item_removed, *removed_value, type_name);
467 }
468 return;
469 }
470 throw ddl::dd::Error(
471 _validation_info + "::remove", {type_name}, "value with the given name does not exist");
472 }
473
480 std::shared_ptr<DDL_TYPE_TO_ACCESS> access(const std::string& type_name)
481 {
482 if (_validator) {
483 const auto named_items = getNamedContainer();
484 auto value_found = named_items->find(type_name);
485 if (value_found != named_items->end()) {
486 return value_found->second;
487 }
488 }
489 else {
490 for (const auto& current: _types) {
491 if (current->getName() == type_name) {
492 return current;
493 }
494 }
495 }
496 return {};
497 }
498
504 size_t getSize() const
505 {
506 return _types.size();
507 }
508
515 {
516 return _types.begin();
517 }
518
525 {
526 return _types.end();
527 }
528
535 {
536 return _types.cbegin();
537 }
538
545 {
546 return _types.cend();
547 }
548
555 {
556 return cbegin();
557 }
558
565 {
566 return cend();
567 }
568
576 bool operator==(const TypeAccessList& other) const
577 {
578 return std::equal(
579 begin(), end(), other.begin(), other.end(), [](const auto& local, const auto& other) {
580 return *(local) == *(other);
581 });
582 }
583
591 bool operator!=(const TypeAccessList& other) const
592 {
593 return !operator==(other);
594 }
595
600 void clear()
601 {
602 for (auto& current: _types) {
603 // unregister me as observer
604 (static_cast<subject_type*>(current.get()))
605 ->detachObserver(static_cast<observer_type*>(this));
606 }
607 if (_validator) {
608 const auto named_items = getNamedContainer();
609 named_items->clear();
610 }
611 _types.clear();
612 }
613
618 void popBack()
619 {
620 if (!_types.empty()) {
621 auto last_element = _types[_types.size() - 1];
622 if (_validator) {
623 _validator->notifyChangedListContent(TypeAccessListEventCode::list_item_removing,
624 *last_element,
625 last_element->getName());
626 }
627 // unregister me as observer
628 (static_cast<subject_type*>(last_element.get()))
629 ->detachObserver(static_cast<observer_type*>(this));
630 // pop last element
631 if (_validator) {
632 const auto named_items = getNamedContainer();
633 named_items->erase(last_element->getName());
634 }
635 _types.pop_back();
636 if (_validator) {
637 _validator->notifyChangedListContent(TypeAccessListEventCode::list_item_popped,
638 *last_element,
639 last_element->getName());
640 }
641 }
642 else {
643 throw ddl::dd::Error(_validation_info + "::popBack", {}, "list is empty");
644 }
645 }
646
647public:
656 subject_type& subject_changed,
657 const std::string& additional_info)
658 {
659 if (event_code == list_item_renaming) {
660 // the validator can not be asked for the renaming here, (because of ABI compatibility, the validateContains can not be changed!)
661 // if you need to have unique names depending on other data structures use the TypeAccessMap instead of TypeAccessList!
662 if (countContains(additional_info) != 0) {
663 throw ddl::dd::Error(
664 _validation_info + "::modelChanged",
665 {additional_info},
666 "Renaming not possible. Value with the given name already exists");
667 }
668 else {
669 if (_validator) {
670 const auto named_items = getNamedContainer();
671 // item will be re-added after renaming
672 named_items->erase(subject_changed.getName());
673 }
674 }
675 }
676 else if (event_code == list_item_renamed) {
677 if (_validator) {
678 const auto named_items = getNamedContainer();
679 for (auto& current: _types) {
680 if (current->getName() == subject_changed.getName()) {
681 named_items->emplace(current->getName(), current);
682 break;
683 }
684 }
685 }
686 }
687 if (_validator) {
688 // i should discover the shared_ptr here, but not needed at the moment
689 _validator->notifyChangedListContent(event_code, subject_changed, additional_info);
690 }
691 }
692
693private:
694 // forward declaration
695 friend class ::ddl::utility::TypeAccessList<DDL_TYPE_TO_ACCESS,
705 void deepCopy(TypeAccessList& destination, TYPE_VALIDATOR_CLASS* validator) const
706 {
707 destination = *this;
708 destination.setValidator(validator);
709 }
717 size_t countContains(const std::string& type_name) const
718 {
719 return std::count_if(_types.begin(), _types.end(), [type_name](const value_type& value) {
720 return value->getName() == type_name;
721 });
722 }
723
724 bool checkExistenceAndEquality(const DDL_TYPE_TO_ACCESS& type_to_add)
725 {
726 // has already another type
727 bool already_exists = false;
728 if (_validator) {
729 already_exists = _validator->validateContains(type_to_add);
730 }
731 else {
732 already_exists = contains(type_to_add.getName());
733 }
734 if (already_exists) {
735 // have a look if the type does exist in this list
736 const auto type_found = get(type_to_add.getName());
737 // have a look if the type already exists here
738 if (type_found) {
739 // check if they are equal
740 if (*type_found == type_to_add) {
741 // its okay ... its the same type/content
742 return true;
743 }
744 throw ddl::dd::Error(_validation_info + "::create",
745 {type_to_add.getName()},
746 "value with the given name already exists and differs in " +
748 *type_found, type_to_add));
749 }
750 else {
751 throw ddl::dd::Error(
752 _validation_info + "::create",
753 {type_to_add.getName()},
754 std::string("value with the given name already exists with another type of ") +
756 }
757 }
758 return false;
759 }
760
761 void setValidator(TYPE_VALIDATOR_CLASS* validator)
762 {
763 _validator = validator;
764 if (_validator) {
765 auto named_items = getNamedContainer();
766 named_items->clear();
767 for (auto& value: _types) {
768 (*named_items)[value->getName()] = value;
769 }
770 }
771 }
772
773 const container_named_type* getNamedContainer() const
774 {
775 // getNamedItemList is dead, but it must be implemented within the _validator for
776 // binary compatibility reason
777 return _validator->getNamedItemViewList();
778 }
779
780 container_named_type* getNamedContainer()
781 {
782 // getNamedItemList is dead, but it must be implemented within the _validator for
783 // binary compatibility reason
784 return _validator->getNamedItemViewList();
785 }
786
787 container_type _types;
788 TYPE_VALIDATOR_CLASS* _validator = {};
789 std::string _validation_info;
790};
791
792} // namespace utility
793} // namespace dd
794
795namespace utility {
796
797// (usually these enums and templates should be moved to utility namespace, but we stay binary
798// compatible for now!)
800
807template <typename T>
809
816template <typename T>
818
825template <typename DDL_TYPE_TO_ACCESS, typename TYPE_VALIDATOR_CLASS>
828 DDL_TYPE_TO_ACCESS,
829 ::ddl::utility::TypeAccessList<DDL_TYPE_TO_ACCESS, TYPE_VALIDATOR_CLASS>> {
830public:
835 DDL_TYPE_TO_ACCESS,
839 friend base_type;
841
845 TypeAccessList() = delete;
851 TypeAccessList(TYPE_VALIDATOR_CLASS* validator, const std::string& validation_info)
852 : base_type(this, validation_info), _validator(validator)
853 {
854 }
855
859 {
860 base_type::_validator = {};
861 }
862
866 TypeAccessList(TypeAccessList&& other) = default;
873
878 TypeAccessList(const TypeAccessList& other) : base_type(this, other._validation_info)
879 {
880 other.deepCopy(*this, this);
881 for (auto& current: *this) {
882 _named_types[current->getName()] = current;
883 }
884 }
885
892 {
893 other.deepCopy(*this, this);
894 for (auto& current: *this) {
895 _named_types[current->getName()] = current;
896 }
897 return *this;
898 }
899
900private:
901 bool validateContains(const typename base_type::access_type& subject) const
902 {
903 if (_validator) {
904 return _validator->validateContains(subject);
905 }
906 return false;
907 }
908
909 void notifyChangedListContent(typename base_type::event_code_type code,
910 typename base_type::access_type& subject,
911 const std::string& additional_info)
912 {
913 if (_validator) {
914 return _validator->notifyChangedListContent(code, subject, additional_info);
915 }
916 }
917
918 const typename base_type::container_named_type* getNamedItemViewList() const
919 {
920 return &_named_types;
921 }
922
923 typename base_type::container_named_type* getNamedItemViewList()
924 {
925 return &_named_types;
926 }
927
928private:
929 typename base_type::container_named_type _named_types;
930 TYPE_VALIDATOR_CLASS* _validator = {};
931};
932
933} // namespace utility
934} // namespace ddl
935
936#endif // DDL_UTILITY_ACCESS_LIST_H_INCLUDED
Exception helper class to collect information while parsing, adding DD Objects or other failed operat...
Definition ddl_error.h:31
The ModelObserver utility template.
Definition access_observer.h:34
TypeAccessListEventCode event_code_type
Definition access_observer.h:37
Model Subject utility to define a Model Subject that notifies one or more observers.
Definition access_observer.h:68
ModelObserverUtility< T, TypeAccessListEventCode > observer_type
Definition access_observer.h:75
Utility class for observable named items where the order is important.
Definition access_list.h:87
std::shared_ptr< Struct > value_type
Definition access_list.h:92
iterator end()
the range based end iterator
Definition access_list.h:524
const_iterator end() const
range based end operator for const access
Definition access_list.h:564
parent_type::event_code_type event_code_type
Definition access_list.h:108
bool operator!=(const TypeAccessList &other) const
non equality operator.
Definition access_list.h:591
Struct access_type
Definition access_list.h:90
void add(const DDL_TYPE_TO_ACCESS &type_to_add)
creates the given item by copy
Definition access_list.h:347
TypeAccessListSubject< Struct > map_subject_type
Definition access_list.h:104
size_t getSize() const
Get the Size.
Definition access_list.h:504
TypeAccessList()=delete
no default CTOR!
TypeAccessList(TYPE_VALIDATOR_CLASS *validator, const std::string &validation_info)
CTOR.
Definition access_list.h:126
bool contains(const TypeAccessList &other) const
determines if the other is a subset of this list
Definition access_list.h:300
TypeAccessListObserver< Struct > parent_type
Definition access_list.h:102
std::shared_ptr< DDL_TYPE_TO_ACCESS > create(DDL_TYPE_TO_ACCESS &&type_to_add)
create the given item by emplace
Definition access_list.h:402
map_subject_type::observer_type observer_type
Definition access_list.h:106
bool contains(const DDL_TYPE_TO_ACCESS &type_to_find) const
determines if the item is in this list.
Definition access_list.h:284
std::shared_ptr< DDL_TYPE_TO_ACCESS > access(const std::string &type_name)
change access to an item
Definition access_list.h:480
std::shared_ptr< const DDL_TYPE_TO_ACCESS > get(std::string_view type_name) const
get the item with the given name type_name
Definition access_list.h:211
void clear()
clears the list and remove this as observer
Definition access_list.h:600
bool contains(const std::string &type_name) const
determines is the type name exists in this list
Definition access_list.h:258
void emplace(DDL_TYPE_TO_ACCESS &&type_to_add)
emplace the given item
Definition access_list.h:432
container_type::iterator iterator
Definition access_list.h:98
void popBack()
removes the last element if exists.
Definition access_list.h:618
std::unordered_map< std::string_view, value_type > container_named_type
Definition access_list.h:96
const_iterator begin() const
range based begin operator for const access
Definition access_list.h:554
const_iterator cbegin() const
const begin iterator access
Definition access_list.h:534
const_iterator cend() const
const end iterator access
Definition access_list.h:544
parent_type::subject_type subject_type
Definition access_list.h:110
bool operator==(const TypeAccessList &other) const
equality operator.
Definition access_list.h:576
void insert(const size_t pos_idx, const DDL_TYPE_TO_ACCESS &type_to_add)
inserts the given item at the given pos
Definition access_list.h:360
friend TYPE_VALIDATOR_CLASS
Definition access_list.h:112
virtual ~TypeAccessList()
DTOR.
Definition access_list.h:134
Optional< size_t > getPosOf(const std::string &type_name) const
Get the Pos Of the item with the name type_name.
Definition access_list.h:238
void remove(const std::string &type_name)
item to remove
Definition access_list.h:442
TypeAccessList(TypeAccessList &&other)
move CTOR
Definition access_list.h:141
TypeAccessList & operator=(TypeAccessList &&other)
move assignment operator
Definition access_list.h:150
std::shared_ptr< DDL_TYPE_TO_ACCESS > create(const DDL_TYPE_TO_ACCESS &type_to_add)
creates the given item by copy
Definition access_list.h:317
TypeAccessList(const TypeAccessList &other)
copies (deepcopy!) CTOR
Definition access_list.h:172
std::vector< value_type > container_type
Definition access_list.h:94
iterator begin()
the range based begin iterator
Definition access_list.h:514
container_type::const_iterator const_iterator
Definition access_list.h:100
TypeAccessList & operator=(const TypeAccessList &other)
copies (deepcopy!) and overwrite the current content.
Definition access_list.h:189
void modelChanged(event_code_type event_code, subject_type &subject_changed, const std::string &additional_info)
overrides the observers utility function.
Definition access_list.h:655
Bug fix class for ddl::dd::utility::TypeAccessList to get rid of providing getNamedItemList in valida...
Definition access_list.h:829
TypeAccessList(const TypeAccessList &other)
copies (deepcopy!) CTOR
Definition access_list.h:878
TypeAccessList()=delete
no default CTOR!
TypeAccessList(TypeAccessList &&other)=default
move CTOR
::ddl::dd::utility::TypeAccessList< ParameterValue, ::ddl::utility::TypeAccessList< ParameterValue, Assignment > > base_type
Definition access_list.h:834
TypeAccessList(TYPE_VALIDATOR_CLASS *validator, const std::string &validation_info)
CTOR.
Definition access_list.h:851
virtual ~TypeAccessList()
DTOR.
Definition access_list.h:858
TypeAccessList & operator=(TypeAccessList &&other)=default
move assignment operator
TypeAccessList & operator=(const TypeAccessList &other)
copies (deepcopy!) and overwrite the current content.
Definition access_list.h:891
definition of the old compatibility utility namespace
Definition datamodel_keyvalue.h:160
ModelObserverUtility< T, TypeAccessListEventCode > TypeAccessListObserver
helper template to observe list content.
Definition access_list.h:78
ModelSubjectUtility< T, TypeAccessListEventCode > TypeAccessListSubject
helper template to observe list content.
Definition access_list.h:69
TypeAccessListEventCode
Internal event code to inform the parent DD Object about the change of an item within the list.
Definition access_list.h:43
definition of the dd namespace
Definition datamodel_base.h:26
@ validation_info
Validation Info.
Definition dd_infomodel_type.h:32
definition of the utility namespace
Definition ddl.h:66
ModelSubjectUtility< T, TypeAccessListEventCode > TypeAccessListSubject
helper template to observe list content.
Definition access_list.h:808
ModelObserverUtility< T, TypeAccessListEventCode > TypeAccessListObserver
helper template to observe list content.
Definition access_list.h:817
definition of the ddl namespace
Definition codec.h:21
An optional template as long as the std::optional is not available here.
Definition access_optional.h:31
static constexpr auto _other_types
validation other types
Definition access_validation.h:41
static std::string getDifference(const T &, const T &)
validation difference message
Definition access_validation.h:45