From 40970893afc57b58b6d2a4676feccc91329b8f85 Mon Sep 17 00:00:00 2001
From: randomdan <randomdan@localhost>
Date: Sun, 14 Sep 2014 23:45:28 +0000
Subject: Fix support for json to deserialize inherited types

---
 slicer/json/serializer.cpp         | 18 ++++++++++++------
 slicer/test/initial/inherit-c.json |  1 +
 slicer/test/run-slicer.cpp         | 33 ++++++++++++++++++++++++++++++++-
 3 files changed, 45 insertions(+), 7 deletions(-)
 create mode 100644 slicer/test/initial/inherit-c.json

diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp
index 0aae914..48b6b36 100644
--- a/slicer/json/serializer.cpp
+++ b/slicer/json/serializer.cpp
@@ -112,7 +112,7 @@ namespace Slicer {
 
 	class DocumentTreeIterate : public boost::static_visitor<> {
 		public:
-			DocumentTreeIterate(ModelPartPtr mp) : modelPart(mp)
+			DocumentTreeIterate(ModelPartPtr & mp) : modelPart(mp)
 			{
 			}
 			template<typename SimpleT>
@@ -128,13 +128,17 @@ namespace Slicer {
 			}
 			void operator()(const json::Object & o) const
 			{
+				auto typeAttrItr = o.find("slicer-typeid");
+				if (typeAttrItr != o.end() && boost::get<json::String>(typeAttrItr->second.get())) {
+					modelPart = modelPart->GetSubclassModelPart(boost::get<json::String>(*typeAttrItr->second));
+				}
 				modelPart->Create();
 				BOOST_FOREACH(const auto & element, o) {
 					auto emp = modelPart->GetChild(element.first);
 					if (emp) {
 						emp->Create();
 						boost::apply_visitor(DocumentTreeIterate(emp), *element.second);
-				emp->Complete();
+						emp->Complete();
 					}
 				}
 				modelPart->Complete();
@@ -147,13 +151,13 @@ namespace Slicer {
 					if (emp) {
 						emp->Create();
 						boost::apply_visitor(DocumentTreeIterate(emp), *element);
-				emp->Complete();
+						emp->Complete();
 					}
 				}
 				modelPart->Complete();
 			}
 		private:
-			ModelPartPtr modelPart;
+			ModelPartPtr & modelPart;
 	};
 
 	void
@@ -241,7 +245,8 @@ namespace Slicer {
 		Glib::ustring doc(buffer.str());
 		Glib::ustring::const_iterator itr = doc.begin();
 		json::Value obj = json::parseValue(itr);
-		boost::apply_visitor(DocumentTreeIterate(modelRoot->GetChild(std::string())), obj);
+		auto mp = modelRoot->GetChild(std::string());
+		boost::apply_visitor(DocumentTreeIterate(mp), obj);
 	}
 
 	void
@@ -261,7 +266,8 @@ namespace Slicer {
 	void
 	JsonValue::Deserialize(ModelPartPtr modelRoot)
 	{
-		boost::apply_visitor(DocumentTreeIterate(modelRoot->GetChild(std::string())), value);
+		auto mp = modelRoot->GetChild(std::string());
+		boost::apply_visitor(DocumentTreeIterate(mp), value);
 	}
 
 	void
diff --git a/slicer/test/initial/inherit-c.json b/slicer/test/initial/inherit-c.json
new file mode 100644
index 0000000..cd5768a
--- /dev/null
+++ b/slicer/test/initial/inherit-c.json
@@ -0,0 +1 @@
+{"b":{"a":1.000000,"b":2.000000,"slicer-typeid":"::TestModule::D1"},"bm":[{"key":10.000000,"value":{"a":11.000000,"b":100.000000,"slicer-typeid":"::TestModule::D1"}},{"key":12.000000,"value":{"a":13.000000,"c":100.000000,"d":200.000000,"slicer-typeid":"::TestModule::D3"}},{"key":14.000000,"value":{"a":15.000000}}],"bs":[{"a":1.000000,"c":100.000000,"slicer-typeid":"::TestModule::D2"},{"a":2.000000,"c":100.000000,"d":200.000000,"slicer-typeid":"::TestModule::D3"},{"a":3.000000}]}
\ No newline at end of file
diff --git a/slicer/test/run-slicer.cpp b/slicer/test/run-slicer.cpp
index 73d5be8..1f0c986 100644
--- a/slicer/test/run-slicer.cpp
+++ b/slicer/test/run-slicer.cpp
@@ -140,6 +140,36 @@ checkBuiltIns_valuesCorrect(const TestModule::BuiltIns & bt)
 	BOOST_ASSERT(bt.mstring == "Sample text");
 }
 
+void
+checkInherits_types(const TestModule::InheritanceCont & i)
+{
+	BOOST_ASSERT(i.b);
+	BOOST_ASSERT(TestModule::D1Ptr::dynamicCast(i.b));
+	BOOST_ASSERT(TestModule::D1Ptr::dynamicCast(i.b)->a == 1);
+	BOOST_ASSERT(TestModule::D1Ptr::dynamicCast(i.b)->b == 2);
+	BOOST_ASSERT(i.bs.size() == 3);
+	BOOST_ASSERT(i.bs[0]);
+	BOOST_ASSERT(TestModule::D2Ptr::dynamicCast(i.bs[0]));
+	BOOST_ASSERT(TestModule::D2Ptr::dynamicCast(i.bs[0])->a == 1);
+	BOOST_ASSERT(TestModule::D2Ptr::dynamicCast(i.bs[0])->c == 100);
+	BOOST_ASSERT(i.bs[1]);
+	BOOST_ASSERT(TestModule::D3Ptr::dynamicCast(i.bs[1]));
+	BOOST_ASSERT(TestModule::D3Ptr::dynamicCast(i.bs[1])->a == 2);
+	BOOST_ASSERT(TestModule::D3Ptr::dynamicCast(i.bs[1])->c == 100);
+	BOOST_ASSERT(TestModule::D3Ptr::dynamicCast(i.bs[1])->d == 200);
+	BOOST_ASSERT(i.bs[2]);
+	BOOST_ASSERT(i.bs[2]->a == 3);
+	BOOST_ASSERT(!TestModule::D1Ptr::dynamicCast(i.bs[2]));
+	BOOST_ASSERT(!TestModule::D2Ptr::dynamicCast(i.bs[2]));
+	BOOST_ASSERT(!TestModule::D3Ptr::dynamicCast(i.bs[2]));
+	BOOST_ASSERT(i.bm.size() == 3);
+	BOOST_ASSERT(TestModule::D1Ptr::dynamicCast(i.bm.find(10)->second));
+	BOOST_ASSERT(TestModule::D3Ptr::dynamicCast(i.bm.find(12)->second));
+	BOOST_ASSERT(!TestModule::D1Ptr::dynamicCast(i.bm.find(14)->second));
+	BOOST_ASSERT(!TestModule::D2Ptr::dynamicCast(i.bm.find(14)->second));
+	BOOST_ASSERT(!TestModule::D3Ptr::dynamicCast(i.bm.find(14)->second));
+}
+
 void
 checkOptionals_notset(const TestModule::Optionals & opts)
 {
@@ -243,10 +273,11 @@ main(int, char ** argv)
 	verifyByFile<TestModule::Optionals, Slicer::XmlFile>(root, tmpf, "optionals-notset.xml", checkOptionals_notset);
 	verifyByFile<TestModule::Optionals, Slicer::XmlFile>(root, tmpf, "optionals-areset.xml", checkOptionals_areset);
 	verifyByFile<TestModule::InheritanceCont, Slicer::XmlFile>(root, tmpf, "inherit-a.xml");
-	verifyByFile<TestModule::InheritanceCont, Slicer::XmlFile>(root, tmpf, "inherit-b.xml");
+	verifyByFile<TestModule::InheritanceCont, Slicer::XmlFile>(root, tmpf, "inherit-b.xml", checkInherits_types);
 	verifyByFile<TestModule::DateTimeContainer, Slicer::XmlFile>(root, tmpf, "conv-datetime.xml");
 	verifyByFile<TestModule::BuiltIns, Slicer::JsonFile>(root, tmpf, "builtins2.json", checkBuiltIns_valuesCorrect);
 	verifyByFile<TestModule::Optionals, Slicer::JsonFile>(root, tmpf, "optionals-areset2.json", checkOptionals_areset);
+	verifyByFile<TestModule::InheritanceCont, Slicer::JsonFile>(root, tmpf, "inherit-c.json", checkInherits_types);
 
 	verifyByHelper<TestModule::Optionals, Slicer::JsonValue, json::Value>(root, tmph, "optionals-areset2.json", readJson, writeJson, freeJson, checkOptionals_areset);
 	verifyByHelper<TestModule::Optionals, Slicer::XmlDocument, xmlpp::Document *>(root, tmph, "optionals-areset.xml", readXml, writeXml, freeXml, checkOptionals_areset);
-- 
cgit v1.2.3