diff --git a/doc/examples/list_serialization.cxx b/doc/examples/list_serialization.cxx index 53b17bc..835fe2c 100644 --- a/doc/examples/list_serialization.cxx +++ b/doc/examples/list_serialization.cxx @@ -17,14 +17,31 @@ class A: public xml::Serialize { xml::List list; protected: void initXmlMembers() { - LOG("A::initXmlMembers"); className("A"); persist(list, "list"); } }; +class B: public xml::Serialize { + public: + int b; + A a; + xml::List as; + protected: + void initXmlMembers() { + className("B"); + persist(b, "b"); + persist(a, "a"); + persist(as, "As"); + } +}; + int main(int, char**) { - std::stringstream ss("\n" + std::stringstream ss("\n" + "1234" + "guguseli" + "" + "\n" "\t\n" "\t\tHello\n" "\t\tWorld\n" @@ -32,12 +49,14 @@ int main(int, char**) { "\t\tare\n" "\t\tyou\n" "\t\n" - ""); - A a; - std::cout<<"Schema:\n"<" + "" + ""); + B b; + std::cout<<"SCHEMA:"< friend class List; Node& operator*() throw(factory_not_valid); Node*const operator->() throw(factory_not_valid); bool ws(char c) throw(); @@ -867,9 +876,16 @@ namespace xml { static void registerToNode(ToNodeFunc toNodeFunc); protected: virtual void initXmlMembers(); + void checkInit(const Serialize* const ser=0) const { + if (ser) { + if (!ser->_xmlFactory) const_cast(ser)->initXmlMembers(); + } else { + if (!_xmlFactory) const_cast(this)->initXmlMembers(); + } + } private: public: //! @todo - void clear() throw(); + void reset() throw(); void copy(const Serialize& o) throw(); template Serialize& persistSimpleType(TYPE& member, @@ -903,25 +919,41 @@ namespace xml { List(const std::string& className) throw(): Serialize(className) {} virtual ~List() {} protected: - /*virtual void initXmlMembers() { - LOG("initXmlMembers std::list"); - //_xmlNames[list] = this; - TYPE dummy; + virtual void initXmlMembers() { std::string itemName("item"); + TYPE tmp; + LOG("initXmlMembers List for: "<_xmlFactory) ser->initXmlMembers(); + LOG("Liste von Serialize"); + Serialize* ser((Serialize*)&tmp); + checkInit(ser); itemName = **ser->_xmlFactory; } - persist(dummy, itemName); - _xmlFactory->limits(0, 0); + _xmlFactory = xml::Node("dummyroot"); // dummy root, (uninitialized exc) + persist(tmp, itemName); // add _reference as child of dummyroot + (*_xmlFactory)[0].limits(0, 0); // any number of children possible } virtual void fromNode(boost::any member, const xml::Node& node) { - LOG("fromNode std::list"); + this->clear(); + for (xml::Node::size_type i(0); i tpl(node.clone()); + xml::Node& parent(node.parent()); + parent.clear(); // "node" is now invalid + for (typename List::const_iterator it = this->begin(); + it!=this->end(); ++it) { + TYPE tmp; + tmp = *it; + std::auto_ptr item(tpl->clone()); + Serialize::toNode(&tmp, *item); + parent<<*item; + } + } }; //@} diff --git a/src/xml.cxx b/src/xml.cxx index c5bae4f..5778656 100644 --- a/src/xml.cxx +++ b/src/xml.cxx @@ -245,7 +245,7 @@ namespace xml { it!=o._contents.end(); ++it) _contents.push_back((*it)->clone(this).release()); } - //! Clones But clears the parent. + //! Clones But resets the parent reference. /*! You get a new instance of the node, but detached from the parent. It is then ready to be inserted below a new parent. @@ -1026,7 +1026,7 @@ namespace xml { copy(other); } Serialize::~Serialize() { - clear(); + reset(); } Serialize& Serialize::operator=(const Serialize& other) throw() { copy(other); @@ -1043,7 +1043,7 @@ namespace xml { } Serialize& Serialize::persist(Serialize& ser, const std::string& name) throw() { - if (!ser._xmlFactory) ser.initXmlMembers(); + ser.checkInit(); _xmlNames[name] = &ser; xml::Node schema(*_xmlFactory); xml::Node node(xml::Node(name).limits(1,1)); @@ -1106,7 +1106,7 @@ namespace xml { } std::ostream& Serialize::saveXml(std::ostream& os, const std::string& name) const throw() { - if (!_xmlFactory) const_cast(this)->initXmlMembers(); + checkInit(); xml::Node node(*_xmlFactory); if (name.size()) node.name(name); for (std::map::const_iterator @@ -1117,7 +1117,7 @@ namespace xml { return os; } std::istream& Serialize::loadXml(std::istream& is, const std::string& name) { - if (!_xmlFactory) initXmlMembers(); + checkInit(); xml::Factory factory(_xmlFactory); if (name.size()) factory->name(name); std::auto_ptr node(factory.read(is)); @@ -1128,21 +1128,54 @@ namespace xml { return is; } std::string Serialize::schema() const throw() { - if (!_xmlFactory) const_cast(this)->initXmlMembers(); + checkInit(); std::stringstream ss; ss<<*_xmlFactory; return ss.str(); } + + void Serialize::registerFromNode(Serialize::FromNodeFunc fromNodeFunc) { + _fromNode.insert(fromNodeFunc); + } + + void Serialize::registerToNode(Serialize::ToNodeFunc toNodeFunc) { + _toNode.insert(toNodeFunc); + } + void Serialize::initXmlMembers() {} + void Serialize::reset() throw() { + _xmlFactory.reset(); + _xmlNames.clear(); + } + void Serialize::copy(const Serialize& o) throw() { + reset(); + initXmlMembers(); + } + void Serialize::fromNode(boost::any member, const xml::Node& node) { + for (std::set::const_iterator it(_fromNode.begin()); + it!=_fromNode.end(); ++it) + if ((**it)(member, node)) return; // found match + throw type_not_registered(member.type().name(), node.name(), node); + } + void Serialize::toNode(const boost::any member, xml::Node& node) const { + for (std::set::const_iterator it(_toNode.begin()); + it!=_toNode.end(); ++it) + if ((**it)(member, node)) return; // found match + throw type_not_registered(member.type().name(), node.name(), node); + } + std::set Serialize::_fromNode; + std::set Serialize::_toNode; + + //=============================================================== Assign Types template bool assignFromNode(boost::any member, const xml::Node& node) { - if (member.type()!=typeid(TYPE*)) return false; + if (!boost::any_cast(&member)) return false; *boost::any_cast(member) = (TYPE)dynamic_cast(node); return true; } template bool assignToNode(const boost::any member, xml::Node& node) { - if (member.type()!=typeid(TYPE*)) return false; + if (!boost::any_cast(&member)) return false; std::stringstream ss; ss<<*boost::any_cast(member); node.text(ss.str()); @@ -1172,66 +1205,26 @@ namespace xml { } template<> bool assignFromNode(boost::any member, const xml::Node& node) { - if (member.type()!=typeid(Serialize*)) return false; + if (!boost::any_cast(&member)) return false; //! @todo improve this (inefficient) std::stringstream ss; // simple but inefficient: rewrite and reread ss<(member)->loadXml(ss, node.name()); + /* + Serialize* ser(boost::any_cast(member)); + for (xml::Node::size_type i(0); ifromNode(ser->_xmlNames[*node[i]], node[i]);*/ return true; } template<> bool assignToNode(const boost::any member, xml::Node& node) { - if (member.type()!=typeid(Serialize*)) return false; + if (!boost::any_cast(&member)) return false; std::stringstream ss; boost::any_cast(member)->saveXml(ss, node.name()); xml::Factory factory(node); node = *factory.read(ss); return true; } -// template class CONTAINER> -// bool containerFromNode(boost::any member, -// const xml::Node& node) { -// if (member.type()!=typeid(TYPE*)) return false; -// LOG("ASSIGN List"); -// return false; -// } -// template -// bool assignToNode(const boost::any member, xml::Node& node) { -// } - - void Serialize::registerFromNode(Serialize::FromNodeFunc fromNodeFunc) { - _fromNode.insert(fromNodeFunc); - } - - void Serialize::registerToNode(Serialize::ToNodeFunc toNodeFunc) { - _toNode.insert(toNodeFunc); - } - void Serialize::initXmlMembers() {} - void Serialize::clear() throw() { - _xmlFactory.reset(); - _xmlNames.clear(); - } - void Serialize::copy(const Serialize& o) throw() { - clear(); - initXmlMembers(); - } - void Serialize::fromNode(boost::any member, const xml::Node& node) { - if (!_fromNode.size()) registerFromNode(&assignFromNode); - for (std::set::const_iterator it(_fromNode.begin()); - it!=_fromNode.end(); ++it) - if ((**it)(member, node)) return; // found match - throw std::runtime_error(node.name()); - } - void Serialize::toNode(const boost::any member, xml::Node& node) const { - if (!_toNode.size()) registerToNode(&assignToNode); - for (std::set::const_iterator it(_toNode.begin()); - it!=_toNode.end(); ++it) - if ((**it)(member, node)) return; // found match - throw std::runtime_error(node.name()); - } - std::set Serialize::_fromNode; - std::set Serialize::_toNode; - // Register for all simple Types ============================================= template struct SimpleTypes {}; template<> struct SimpleTypes<1> {typedef std::string Type;};