24
#include "PreCompiled.h"
26
#include <Base/Console.h>
27
#include <Base/Exception.h>
28
#include <Base/Reader.h>
29
#include <Base/Writer.h>
32
#include "ExtensionContainer.h"
37
TYPESYSTEM_SOURCE(App::ExtensionContainer, App::PropertyContainer)
39
ExtensionContainer::ExtensionContainer() = default;
41
ExtensionContainer::~ExtensionContainer() {
44
for(const auto& entry : _extensions) {
45
if(entry.second->isPythonExtension())
50
void ExtensionContainer::registerExtension(Base::Type extension, Extension* ext) {
51
if(ext->getExtendedContainer() != this)
52
throw Base::ValueError("ExtensionContainer::registerExtension: Extension has not this as base object");
55
if(hasExtension(extension)) {
56
for(const auto& entry : _extensions) {
57
if(entry.first == extension || entry.first.isDerivedFrom(extension)) {
58
_extensions.erase(entry.first);
64
_extensions[extension] = ext;
67
bool ExtensionContainer::hasExtension(Base::Type t, bool derived) const {
70
bool found = _extensions.find(t) != _extensions.end();
71
if(!found && derived) {
73
for(const auto& entry : _extensions) {
74
if(entry.first.isDerivedFrom(t))
82
bool ExtensionContainer::hasExtension(const std::string& name) const {
85
for(const auto& entry : _extensions) {
86
if(entry.second->name() == name)
93
Extension* ExtensionContainer::getExtension(Base::Type t, bool derived, bool no_except) const {
95
auto result = _extensions.find(t);
96
if((result == _extensions.end()) && derived) {
98
for(const auto& entry : _extensions) {
99
if(entry.first.isDerivedFrom(t))
105
throw Base::TypeError("ExtensionContainer::getExtension: No extension of given type available");
107
else if (result != _extensions.end()) {
108
return result->second;
114
throw Base::TypeError("ExtensionContainer::getExtension: No extension of given type available");
118
bool ExtensionContainer::hasExtensions() const {
120
return !_extensions.empty();
123
Extension* ExtensionContainer::getExtension(const std::string& name) const {
126
for(const auto& entry : _extensions) {
127
if(entry.second->name() == name)
133
std::vector< Extension* > ExtensionContainer::getExtensionsDerivedFrom(Base::Type type) const {
135
std::vector<Extension*> vec;
137
for(const auto& entry : _extensions) {
138
if(entry.first.isDerivedFrom(type))
139
vec.push_back(entry.second);
144
void ExtensionContainer::getPropertyList(std::vector< Property* >& List) const {
145
App::PropertyContainer::getPropertyList(List);
146
for(const auto& entry : _extensions)
147
entry.second->extensionGetPropertyList(List);
150
void ExtensionContainer::getPropertyMap(std::map< std::string, Property* >& Map) const {
151
App::PropertyContainer::getPropertyMap(Map);
152
for(const auto& entry : _extensions)
153
entry.second->extensionGetPropertyMap(Map);
156
Property* ExtensionContainer::getPropertyByName(const char* name) const {
157
auto prop = App::PropertyContainer::getPropertyByName(name);
161
for(const auto& entry : _extensions) {
162
auto prop = entry.second->extensionGetPropertyByName(name);
171
short int ExtensionContainer::getPropertyType(const Property* prop) const {
172
short int res = App::PropertyContainer::getPropertyType(prop);
176
for(const auto& entry : _extensions) {
177
res = entry.second->extensionGetPropertyType(prop);
185
short int ExtensionContainer::getPropertyType(const char* name) const {
187
short int res = App::PropertyContainer::getPropertyType(name);
191
for(const auto& entry : _extensions) {
192
res = entry.second->extensionGetPropertyType(name);
201
const char* ExtensionContainer::getPropertyName(const Property* prop) const {
203
const char* res = App::PropertyContainer::getPropertyName(prop);
207
for (const auto& entry : _extensions) {
208
res = entry.second->extensionGetPropertyName(prop);
216
const char* ExtensionContainer::getPropertyGroup(const Property* prop) const {
218
const char* res = App::PropertyContainer::getPropertyGroup(prop);
222
for (const auto& entry : _extensions) {
223
res = entry.second->extensionGetPropertyGroup(prop);
231
const char* ExtensionContainer::getPropertyGroup(const char* name) const {
233
const char* res = App::PropertyContainer::getPropertyGroup(name);
237
for (const auto& entry : _extensions) {
238
res = entry.second->extensionGetPropertyGroup(name);
247
const char* ExtensionContainer::getPropertyDocumentation(const Property* prop) const {
249
const char* res = App::PropertyContainer::getPropertyDocumentation(prop);
253
for (const auto& entry : _extensions) {
254
res = entry.second->extensionGetPropertyDocumentation(prop);
262
const char* ExtensionContainer::getPropertyDocumentation(const char* name) const {
264
const char* res = App::PropertyContainer::getPropertyDocumentation(name);
268
for(const auto& entry : _extensions) {
269
res = entry.second->extensionGetPropertyDocumentation(name);
277
void ExtensionContainer::onChanged(const Property* prop) {
281
for(const auto& entry : _extensions)
282
entry.second->extensionOnChanged(prop);
284
App::PropertyContainer::onChanged(prop);
287
void ExtensionContainer::Save(Base::Writer& writer) const {
293
saveExtensions(writer);
294
App::PropertyContainer::Save(writer);
297
void ExtensionContainer::Restore(Base::XMLReader& reader) {
305
restoreExtensions(reader);
306
App::PropertyContainer::Restore(reader);
309
void ExtensionContainer::saveExtensions(Base::Writer& writer) const {
317
writer.Stream() << writer.ind() << "<Extensions Count=\"" << _extensions.size() << "\">" << std::endl;
318
for(const auto& entry : _extensions) {
320
auto ext = entry.second;
322
writer.Stream() << writer.ind() << "<Extension"
323
<< " type=\"" << ext->getExtensionTypeId().getName() <<"\""
324
<< " name=\"" << ext->name() << "\">" << std::endl;
330
ext->extensionSave(writer);
332
catch (const Base::Exception &e) {
333
Base::Console().Error("%s\n", e.what());
335
catch (const std::exception &e) {
336
Base::Console().Error("%s\n", e.what());
338
catch (const char* e) {
339
Base::Console().Error("%s\n", e);
343
Base::Console().Error("ExtensionContainer::Save: Unknown C++ exception thrown. Try to continue...\n");
347
writer.Stream() << writer.ind() << "</Extension>" << std::endl;
350
writer.Stream() << writer.ind() << "</Extensions>" << std::endl;
354
void ExtensionContainer::restoreExtensions(Base::XMLReader& reader) {
360
if(!reader.hasAttribute("Extensions"))
363
reader.readElement("Extensions");
364
int Cnt = reader.getAttributeAsInteger("Count");
366
for (int i=0 ;i<Cnt ;i++) {
367
reader.readElement("Extension");
368
const char* Type = reader.getAttribute("type");
369
const char* Name = reader.getAttribute("name");
371
App::Extension* ext = getExtension(Name);
374
Base::Type extension = Base::Type::fromName(Type);
375
if (extension.isBad() || !extension.isDerivedFrom(App::Extension::getExtensionClassTypeId())) {
376
std::stringstream str;
377
str << "No extension found of type '" << Type << "'" << std::ends;
378
throw Base::TypeError(str.str());
382
ext = static_cast<App::Extension*>(extension.createInstance());
384
if (!ext->isPythonExtension()) {
386
std::stringstream str;
387
str << "Extension is not a python addable version: '" << Type << "'";
388
throw Base::TypeError(str.str());
391
ext->initExtension(this);
393
if (ext && strcmp(ext->getExtensionTypeId().getName(), Type) == 0)
394
ext->extensionRestore(reader);
396
catch (const Base::XMLParseException&) {
399
catch (const Base::Exception &e) {
400
Base::Console().Error("%s\n", e.what());
402
catch (const std::exception &e) {
403
Base::Console().Error("%s\n", e.what());
405
catch (const char* e) {
406
Base::Console().Error("%s\n", e);
410
Base::Console().Error("ExtensionContainer::Restore: Unknown C++ exception thrown\n");
414
reader.readEndElement("Extension");
416
reader.readEndElement("Extensions");
419
void ExtensionContainer::handleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName)
423
for(const auto& entry : _extensions) {
424
bool handled = entry.second->extensionHandleChangedPropertyName(reader, TypeName, PropName);
430
PropertyContainer::handleChangedPropertyName(reader, TypeName, PropName);
433
void ExtensionContainer::handleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, Property * prop)
437
for(const auto& entry : _extensions) {
438
bool handled = entry.second->extensionHandleChangedPropertyType(reader, TypeName, prop);
444
PropertyContainer::handleChangedPropertyType(reader, TypeName, prop);