ICF 3.0.5.47
Technical documentation of ICF Libraries
TFactorisableContainer.h
Go to the documentation of this file.
1/********************************************************************************
2** This file is part of the ICF Framework. Copyright (C) Witold Gantzke & Kirill Lepskiy
3** ICF Framework may be used under the terms of the LGPL License v. 2.1 by the Free Software Foundation.
4********************************************************************************/
5
6#pragma once
7
8
9// Qt includes
10#include <QtCore/QPair>
11
12// ICF includes
13#include <istd/TIFactory.h>
15
16
17namespace ibase
18{
19
20
28template <class InterfaceClass>
31 QPair<std::shared_ptr<InterfaceClass>, QByteArray> >
32{
33public:
34 typedef QPair<std::shared_ptr<InterfaceClass>, QByteArray> ItemClass;
36
39
43 InterfaceClass* InsertElement(int index, const QByteArray& elementFactoryKey);
44
48 InterfaceClass* AddElement(const QByteArray& elementFactoryKey);
49
55 InterfaceClass* GetElement(int elementIndex) const;
56
60 int GetElementIndex(const InterfaceClass& elementRef) const;
61
65 QByteArray GetElementKey(int elementIndex) const;
66
68
69 // reimplemented (iser::ISerializable)
70 bool Serialize(iser::IArchive& archive);
71
72protected:
73 virtual std::unique_ptr<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);
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 auto elementPtr = CreateElement(elementFactoryKey);
102 if (element != nullptr){
103 BaseClass::PushBack(ItemClass(elementPtr, elementFactoryKey));
104 }
105
106 return elementPtr.get();
107}
108
109
110template <class InterfaceClass>
111InterfaceClass* TFactorisableContainer<InterfaceClass>::InsertElement(int index, const QByteArray& elementFactoryKey)
112{
113 auto elementPtr = CreateElement(elementFactoryKey);
114 if (element != nullptr){
115 BaseClass::InsertAt(ItemClass(elementPtr, elementFactoryKey), index);
116 }
117
118 return elementPtr.get();
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.get());
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 bool isChanging = archive.IsChanging();
175 istd::CChangeNotifier notifier(isChanging? this: nullptr, &istd::IChangeable::GetAllChanges());
176
177 if (isChanging){
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 (!isChanging){
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 (isChanging) {
203 item.second = itemKey;
204 auto interfacePtr = CreateElement(itemKey);
205 if (interfacePtr != nullptr){
206 item.first = std::shared_ptr<InterfaceClass>{interfacePtr.release()};
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>
231std::unique_ptr<InterfaceClass> TFactorisableContainer<InterfaceClass>::CreateElement(const QByteArray& itemKey)
232{
233 if (m_itemFactoryPtr != nullptr){
234 auto polymorphicPtr = m_itemFactoryPtr->CreateInstance(itemKey);
235 if (polymorphicPtr != nullptr){
236 InterfaceClass* interfacePtr = dynamic_cast<InterfaceClass*>(polymorphicPtr);
237 if (interfacePtr != nullptr){
238 OnElementCreated(interfacePtr);
239
240 return std::shared_ptr<InterfaceClass>{interfacePtr};
241 }
242 else{
243 delete polymorphicPtr;
244
245 return nullptr;
246 }
247 }
248 }
249
250 return nullptr;
251}
252
253
254template <class InterfaceClass>
256{
257}
258
259
260// reimplemented (ibase::TContainer)
261
262template <class InterfaceClass>
264{
265 iser::ISerializable* serializablePtr = dynamic_cast<iser::ISerializable*>(item.first.get());
266 if (serializablePtr != nullptr){
267 return serializablePtr->Serialize(archive);
268 }
269
270 return false;
271}
272
273
274} // namespace ibase
275
276
Specific container implementation for factorisable items.
virtual bool SerializeItem(ItemClass &item, iser::IArchive &archive, iser::CArchiveTag *parentTagPtr=nullptr)
Serialize a single item in the container.
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.
ibase::TSerializableContainer< ItemClass > BaseClass
QPair< std::shared_ptr< InterfaceClass >, QByteArray > ItemClass
InterfaceClass * InsertElement(int index, const QByteArray &elementFactoryKey)
Insert an element into the container at given index.
QByteArray GetElementKey(int elementIndex) const
Gets the element key associated with the element with given elementIndex from the container.
virtual void OnElementCreated(InterfaceClass *elementPtr)
virtual std::unique_ptr< InterfaceClass > CreateElement(const QByteArray &itemKey)
istd::TIFactory< InterfaceClass > * m_itemFactoryPtr
void RegisterItemFactory(istd::TIFactory< InterfaceClass > *itemFactoryPtr)
bool Serialize(iser::IArchive &archive)
Load or store state of this object as a archive stream.
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:25
@ TT_GROUP
Normal tag used for grouping of tags or processed elements.
Definition CArchiveTag.h:40
@ TT_LEAF
Leaf tag, it can contain only one primitive element.
Definition CArchiveTag.h:51
@ TT_MULTIPLE
Multiple tag containing variable number of child tags.
Definition CArchiveTag.h:45
Represent input/output persistence archive.
Definition IArchive.h:33
virtual bool Process(bool &value)=0
Process primitive type.
virtual bool EndTag(const CArchiveTag &tag)=0
End of archive tag.
virtual bool BeginMultiTag(const CArchiveTag &tag, const CArchiveTag &subTag, int &count)=0
Begin of archive tag containing set of subelements of the same type.
virtual bool IsChanging() const =0
Check if this archive processing change the object state.
virtual bool BeginTag(const CArchiveTag &tag)=0
Begin of archive tag.
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:22
This namespace contains standard classes based on Qt.

© Witold Gantzke and Kirill Lepskiy