예제 #1
0
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");
}