#ifndef _PolyXML_h_ #define _PolyXML_h_ #include NAMESPACE_UPP; template class WithPolyXML : public WithFactory { public: // Xmlizer virtual void Xmlize(XmlIO &xml) {}; // Check if object is marked as erased so the array don't store it on xml // useful if you don't remove objects from array but just mark them as erased // to be redefined if you need this feature ! virtual bool IsErased(void) { return false; } }; template class PolyXMLUnknown : public T { private: String tag; String rawXML; public: PolyXMLUnknown(String const &_tag, String const &xml) { tag = _tag; rawXML = xml; } virtual String const &IsA(void) { return CLASSFACTORY_UNKNOWN; } String const &GetUnknownClassName(void) { return tag; } virtual void Xmlize(XmlIO &xml) { if(xml.IsStoring()) { XmlNode node = ParseXML(rawXML); xml.Add(); xml.Node() = node; } } }; //////////////////////////////////////////////////////////////////////////////////////////////// // PolyXMLArray class -- add support for streaming polymorphic arrays of objects template class PolyXMLArray : public Array { public: // Xmlizer void Xmlize(XmlIO &xml); T& Add(const T &data) { return Array::Add(data); } T& Add(T *data) { return Array::Add(data); } // progress callback Callback2Progress; }; template void PolyXMLArray::Xmlize(XmlIO &xml) { if(xml.IsStoring()) { int count = PolyXMLArray::GetCount(); for(int i = 0; i < count; i++) { Progress(i, count); T &data = PolyXMLArray::operator[](i); if(!data.IsErased()) { String tag = data.IsA(); XmlIO io = xml.Add(tag); data.Xmlize(io); } } } else { PolyXMLArray::Clear(); int count = xml->GetCount(); for(int i = 0; i < count; i++) { Progress(i, count); if(xml->Node(i).IsTag()) { String tag = xml->Node(i).GetTag(); T *data = T::CreatePtr(tag); if(data) { XmlIO io = xml.At(i); data->Xmlize(io); Add(data); } else { // unknown class -- gather raw xml node String rawXml = AsXML(xml.At(i).Node()); // strips xml header, we don't need it // rawXml = rawXml.Mid(rawXml.Find(xml->Node(i).GetTag())); // creates an unknown class and stores raw xml on it Add((T *)new PolyXMLUnknown(tag, rawXml)); } } } } } //////////////////////////////////////////////////////////////////////////////////////////////// // PolyXMLArrayMap class -- add support for streaming polymorphic maps of objects template class PolyXMLArrayMap : public ArrayMap { public: // Xmlizer void Xmlize(XmlIO &xml); T& Add(const K &key, const T &data) { return ArrayMap::Add(key, data); } T& Add(const K &key, T *data) { return ArrayMap::Add(key, data); } // progress callback Callback2Progress; }; template void PolyXMLArrayMap::Xmlize(XmlIO &xml) { if(xml.IsStoring()) { int count = PolyXMLArrayMap::GetCount(); for(int i = 0; i < count; i++) { Progress(i, count); // skip unlinked elements if(ArrayMap::IsUnlinked(i)) continue; T &data = PolyXMLArrayMap::operator[](i); K const &key = PolyXMLArrayMap::GetKey(i); // skip data marked as erase too if(data.IsErased()) continue; String tag = data.IsA(); XmlIO ioKey = xml.Add("key"); XmlizeStore(ioKey, key); XmlIO ioTag = xml.Add(tag); XmlizeStore(ioTag, data); } } else { PolyXMLArrayMap::Clear(); int count = xml->GetCount() - 1; for(int i = 0; i < count && xml->Node(i).IsTag("key");) { Progress(i, count); if(xml->Node(i).IsTag()) { K key; XmlIO io = xml.At(i++); Upp::Xmlize(io, key); String tag = xml->Node(i).GetTag(); T *data = T::CreatePtr(tag); if(data) { XmlIO io = xml.At(i++); data->Xmlize(io); Add(key, data); } else { // unknown class -- gather raw xml node String rawXml = AsXML(xml.At(i).Node()); // creates an unknown class and stores raw xml on it Add(key, (T *)new PolyXMLUnknown(tag, rawXml)); } } } } } //////////////////////////////////////////////////////////////////////////////////////////////// // PolyXMLArrayMapOne class -- add support for streaming polymorphic maps of One<> objects template class PolyXMLArrayMapOne : public ArrayMap > { public: // Xmlizer void Xmlize(XmlIO &xml); One& Add(const K &key, pick_ One &data) { return ArrayMap >::AddPick(key, data); } // progress callback Callback2Progress; }; template void PolyXMLArrayMapOne::Xmlize(XmlIO &xml) { if(xml.IsStoring()) { int count = PolyXMLArrayMapOne::GetCount(); for(int i = 0; i < count; i++) { Progress(i, count); // skip unlinked elements if(ArrayMap >::IsUnlinked(i)) continue; One &data = PolyXMLArrayMapOne::operator[](i); K const &key = PolyXMLArrayMapOne::GetKey(i); // skip data marked as erase too if(data->IsErased()) continue; String tag = data->IsA(); XmlIO ioKey = xml.Add("key"); XmlizeStore(ioKey, key); XmlIO ioTag = xml.Add(tag); XmlizeStore(ioTag, *data); } } else { PolyXMLArrayMapOne::Clear(); int count = xml->GetCount() - 1; for(int i = 0; i < count && xml->Node(i).IsTag("key");) { Progress(i, count); if(xml->Node(i).IsTag()) { K key; XmlIO io = xml.At(i++); Upp::Xmlize(io, key); String tag = xml->Node(i).GetTag(); One data = T::CreatePtr(tag); if(data) { XmlIO io = xml.At(i++); data->Xmlize(io); Add(key, data); } else { // unknown class -- gather raw xml node String rawXml = AsXML(xml.At(i).Node()); // creates an unknown class and stores raw xml on it One raw = (T *)new PolyXMLUnknown(tag, rawXml); Add(key, raw); } } } } } END_UPP_NAMESPACE; #endif