void DynamicProperty::Restore(Base::XMLReader &reader) { //first all extensions must be initialised so that they can handle their properties if(this->pc->isDerivedFrom(App::ExtensionContainer::getClassTypeId())) static_cast<App::ExtensionContainer*>(this->pc)->restoreExtensions(reader); reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ; i<Cnt ; i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); Property* prop = getPropertyByName(PropName); try { if (!prop) { short attribute = 0; bool readonly = false, hidden = false; const char *group=0, *doc=0, *attr=0, *ro=0, *hide=0; if (reader.hasAttribute("group")) group = reader.getAttribute("group"); if (reader.hasAttribute("doc")) doc = reader.getAttribute("doc"); if (reader.hasAttribute("attr")) { attr = reader.getAttribute("attr"); if (attr) attribute = attr[0]-48; } if (reader.hasAttribute("ro")) { ro = reader.getAttribute("ro"); if (ro) readonly = (ro[0]-48) != 0; } if (reader.hasAttribute("hide")) { hide = reader.getAttribute("hide"); if (hide) hidden = (hide[0]-48) != 0; } prop = addDynamicProperty(TypeName, PropName, group, doc, attribute, readonly, hidden); } } catch(const Base::Exception& e) { // only handle this exception type Base::Console().Warning(e.what()); } //NOTE: We must also check the type of the current property because a subclass of //PropertyContainer might change the type of a property but not its name. In this //case we would force to read-in a wrong property type and the behaviour would be //undefined. // Don't read transient properties if (!(getPropertyType(prop) & Prop_Transient)) { if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0) { try { prop->Restore(reader); } catch (const Base::XMLParseException&) { throw; // re-throw } catch (const Base::Exception &e) { Base::Console().Error("%s\n", e.what()); } catch (const std::exception &e) { Base::Console().Error("%s\n", e.what()); } #ifndef FC_DEBUG catch (...) { Base::Console().Error("DynamicProperty::Restore: Unknown C++ exception thrown"); } #endif } else if (prop) { Base::Console().Warning("%s: Overread data for property %s of type %s, expected type is %s\n", pc->getTypeId().getName(), prop->getName(), prop->getTypeId().getName(), TypeName); } else { Base::Console().Warning("%s: No property found with name %s and type %s\n", pc->getTypeId().getName(), PropName, TypeName); } } reader.readEndElement("Property"); } reader.readEndElement("Properties"); }
void PropertyContainer::Restore(Base::XMLReader &reader) { reader.clearPartialRestoreProperty(); reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ;i<Cnt ;i++) { reader.readElement("Property"); std::string PropName = reader.getAttribute("name"); std::string TypeName = reader.getAttribute("type"); Property* prop = getPropertyByName(PropName.c_str()); // NOTE: We must also check the type of the current property because a // subclass of PropertyContainer might change the type of a property but // not its name. In this case we would force to read-in a wrong property // type and the behaviour would be undefined. try { // name and type match if (prop && strcmp(prop->getTypeId().getName(), TypeName.c_str()) == 0) { prop->Restore(reader); } // name matches but not the type else if (prop) { handleChangedPropertyType(reader, TypeName.c_str(), prop); } // name doesn't match, the sub-class then has to know // if the property has been renamed or removed else { handleChangedPropertyName(reader, TypeName.c_str(), PropName.c_str()); } if (reader.testStatus(Base::XMLReader::ReaderStatus::PartialRestoreInProperty)) { Base::Console().Error("Property %s of type %s was subject to a partial restore.\n",PropName.c_str(),TypeName.c_str()); reader.clearPartialRestoreProperty(); } } catch (const Base::XMLParseException&) { throw; // re-throw } catch (const Base::RestoreError &) { reader.setPartialRestore(true); reader.clearPartialRestoreProperty(); Base::Console().Error("Property %s of type %s was subject to a partial restore.\n",PropName.c_str(),TypeName.c_str()); } catch (const Base::Exception &e) { Base::Console().Error("%s\n", e.what()); } catch (const std::exception &e) { Base::Console().Error("%s\n", e.what()); } catch (const char* e) { Base::Console().Error("%s\n", e); } #ifndef FC_DEBUG catch (...) { Base::Console().Error("PropertyContainer::Restore: Unknown C++ exception thrown\n"); } #endif reader.readEndElement("Property"); } reader.readEndElement("Properties"); }