ACF $AcfVersion:0$
TFactorisableContainer.h
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-2.1-or-later OR GPL-2.0-or-later OR GPL-3.0-or-later OR LicenseRef-ACF-Commercial
2#pragma once
3
4
5// Qt includes
6#include <QtCore/QPair>
7
8// ACF includes
9#include <istd/TSmartPtr.h>
10#include <istd/TIFactory.h>
12
13
14namespace ibase
15{
16
17
25template <class InterfaceClass>
28 QPair<istd::TSmartPtr<InterfaceClass>, QByteArray> >
29{
30public:
31 typedef QPair<istd::TSmartPtr<InterfaceClass>, QByteArray> ItemClass;
33
36
40 InterfaceClass* InsertElement(int index, const QByteArray& elementFactoryKey);
41
45 InterfaceClass* AddElement(const QByteArray& elementFactoryKey);
46
52 InterfaceClass* GetElement(int elementIndex) const;
53
57 int GetElementIndex(const InterfaceClass& elementRef) const;
58
62 QByteArray GetElementKey(int elementIndex) const;
63
68
69 // reimplemented (iser::ISerializable)
70 virtual bool Serialize(iser::IArchive& archive) override;
71
72protected:
73 virtual InterfaceClass* CreateElement(const QByteArray& itemKey);
74 virtual void OnElementCreated(InterfaceClass* elementPtr);
75
76 // reimplemented (ibase::TSerializableContainer)
77 virtual bool SerializeItem(ItemClass& item, iser::IArchive& archive, iser::CArchiveTag* parentTagPtr = nullptr) override;
78
79protected:
81};
82
83
84template <class InterfaceClass>
89
90
91template <class InterfaceClass>
96
97
98template <class InterfaceClass>
99InterfaceClass* TFactorisableContainer<InterfaceClass>::AddElement(const QByteArray& elementFactoryKey)
100{
101 istd::TSmartPtr<InterfaceClass> elementPtr(CreateElement(elementFactoryKey));
102 if (elementPtr.IsValid()){
103 BaseClass::PushBack(ItemClass(elementPtr, elementFactoryKey));
104 }
105
106 return elementPtr.GetPtr();
107}
108
109
110template <class InterfaceClass>
111InterfaceClass* TFactorisableContainer<InterfaceClass>::InsertElement(int index, const QByteArray& elementFactoryKey)
112{
113 istd::TSmartPtr<InterfaceClass> elementPtr(CreateElement(elementFactoryKey));
114 if (elementPtr.IsValid()){
115 BaseClass::InsertAt(ItemClass(elementPtr, elementFactoryKey), index);
116 }
117
118 return elementPtr.GetPtr();
119}
120
121
122template <class InterfaceClass>
123InterfaceClass* TFactorisableContainer<InterfaceClass>::GetElement(int elementIndex) const
124{
125 if (elementIndex < BaseClass::GetItemsCount() && elementIndex >= 0){
126 return const_cast<InterfaceClass*>(BaseClass::GetAt(elementIndex).first.GetPtr());
127 }
128
129 return nullptr;
130}
131
132
133template <class InterfaceClass>
134int TFactorisableContainer<InterfaceClass>::GetElementIndex(const InterfaceClass& elementRef) const
135{
136 for (int itemIndex = 0; itemIndex < BaseClass::GetItemsCount(); itemIndex++){
137 InterfaceClass* elementPtr = GetElement(itemIndex);
138 if (elementPtr == &elementRef){
139 return itemIndex;
140 }
141 }
142
143 return -1;
144}
145
146
147template <class InterfaceClass>
149{
150 if (elementIndex < BaseClass::GetItemsCount() && elementIndex >= 0){
151 return BaseClass::GetAt(elementIndex).second;
152 }
153
154 return QByteArray();
155}
156
157
158template <class InterfaceClass>
160{
161 m_itemFactoryPtr = itemFactoryPtr;
162}
163
164
165// reimplemented (iser::ISerializable)
166
167template <class InterfaceClass>
169{
170 static iser::CArchiveTag itemsTag("Items", "List of items", iser::CArchiveTag::TT_MULTIPLE);
171 static iser::CArchiveTag itemTag("Item", "Item", iser::CArchiveTag::TT_GROUP, &itemsTag);
172 static iser::CArchiveTag keyTag("ItemKey", "Factory key of the item", iser::CArchiveTag::TT_LEAF, &itemTag);
173
174 istd::CChangeNotifier notifier(archive.IsStoring()? nullptr: this, &istd::IChangeable::GetAllChanges());
175 Q_UNUSED(notifier);
176
177 if (!archive.IsStoring()){
178 this->Reset();
179 }
180
181 int itemCount = BaseClass::GetItemsCount();
182
183 bool retVal = archive.BeginMultiTag(itemsTag, itemTag, itemCount);
184 if (!retVal){
185 return false;
186 }
187
188 for (int index = 0; index < itemCount; index++){
189 retVal = retVal && archive.BeginTag(itemTag);
190
191 ItemClass item;
192 QByteArray itemKey;
193
194 if (archive.IsStoring()){
195 itemKey = BaseClass::GetAt(index).second;
196 }
197
198 retVal = retVal && archive.BeginTag(keyTag);
199 retVal = retVal && archive.Process(itemKey);
200 retVal = retVal && archive.EndTag(keyTag);
201
202 if (!archive.IsStoring()){
203 item.second = itemKey;
204 InterfaceClass* interfacePtr = CreateElement(itemKey);
205 if (interfacePtr != nullptr){
206 item.first.SetPtr(interfacePtr);
207
208 BaseClass::PushBack(item);
209 }
210 else{
211 return false;
212 }
213 }
214
215 ItemClass& containerItem = BaseClass::GetAt(index);
216
217 retVal = retVal && SerializeItem(containerItem, archive, &itemTag);
218
219 retVal = retVal && archive.EndTag(itemTag);
220 }
221
222 retVal = retVal && archive.EndTag(itemsTag);
223
224 return retVal;
225}
226
227
228// protected methods
229
230template <class InterfaceClass>
231InterfaceClass* TFactorisableContainer<InterfaceClass>::CreateElement(const QByteArray& itemKey)
232{
233 if (m_itemFactoryPtr != nullptr){
234 auto polymorphicPtr = m_itemFactoryPtr->CreateInstance(itemKey);
235 if (polymorphicPtr.IsValid()){
236 InterfaceClass* interfacePtr = polymorphicPtr.GetPtr();
237 if (interfacePtr != nullptr){
238 OnElementCreated(interfacePtr);
239
240 return polymorphicPtr.PopPtr();
241 }
242 // else: polymorphicPtr will be automatically deleted
243 }
244 }
245
246 return nullptr;
247}
248
249
250template <class InterfaceClass>
252{
253}
254
255
256// reimplemented (ibase::TContainer)
257
258template <class InterfaceClass>
260{
261 iser::ISerializable* serializablePtr = dynamic_cast<iser::ISerializable*>(item.first.GetPtr());
262 if (serializablePtr != nullptr){
263 return serializablePtr->Serialize(archive);
264 }
265
266 return false;
267}
268
269
270} // namespace ibase
271
272
Specific container implementation for factorisable items.
InterfaceClass * GetElement(int elementIndex) const
Gets an element with given index elementIndex from the container.
int GetElementIndex(const InterfaceClass &elementRef) const
Gets the index of given element from the container.
QPair< istd::TSmartPtr< InterfaceClass >, QByteArray > ItemClass
ibase::TSerializableContainer< ItemClass > BaseClass
InterfaceClass * InsertElement(int index, const QByteArray &elementFactoryKey)
Insert an element into the container at given index.
virtual InterfaceClass * CreateElement(const QByteArray &itemKey)
QByteArray GetElementKey(int elementIndex) const
Gets the element key associated with the element with given elementIndex from the container.
virtual bool SerializeItem(ItemClass &item, iser::IArchive &archive, iser::CArchiveTag *parentTagPtr=nullptr) override
Serialize a single item in the container.
virtual void OnElementCreated(InterfaceClass *elementPtr)
istd::TIFactory< InterfaceClass > * m_itemFactoryPtr
virtual bool Serialize(iser::IArchive &archive) override
Load or store state of this object as a archive stream.
void RegisterItemFactory(istd::TIFactory< InterfaceClass > *itemFactoryPtr)
Register factory instance for creation of container items.
InterfaceClass * AddElement(const QByteArray &elementFactoryKey)
Add an element to the container.
Common implementation for an abstract serializable container.
Process tag used to group data in archive stream.
Definition CArchiveTag.h:22
@ TT_GROUP
Normal tag used for grouping of tags or processed elements.
Definition CArchiveTag.h:37
@ TT_LEAF
Leaf tag, it can contain only one primitive element.
Definition CArchiveTag.h:48
@ TT_MULTIPLE
Multiple tag containing variable number of child tags.
Definition CArchiveTag.h:42
Represents an input/output persistence archive for object serialization.
Definition IArchive.h:164
virtual bool Process(bool &value)=0
Processes (reads or writes) a boolean value.
virtual bool EndTag(const CArchiveTag &tag)=0
Ends a tagged section in the archive.
virtual bool BeginMultiTag(const CArchiveTag &tag, const CArchiveTag &subTag, int &count)=0
Begins a tagged section containing multiple elements of the same type.
virtual bool IsStoring() const =0
Checks if this archive is in storing (writing) or loading (reading) mode.
virtual bool BeginTag(const CArchiveTag &tag)=0
Begins a tagged section in the archive.
Common class for all classes which objects can be archived or restored from archive.
virtual bool Serialize(IArchive &archive)=0
Load or store state of this object as a archive stream.
Help class which provides the automatic update mechanism of the model.
static const ChangeSet & GetAllChanges()
Get anonymous change set.
Generic interface for a factory.
Definition TIFactory.h:19
const Type * GetPtr() const
Get access to pointed object.
Definition TTransPtr.h:80
bool IsValid() const
Check, whether the object is in valid state.
Definition TTransPtr.h:73
This namespace contains basic implementations of standard primitives on the component level.