diff options
| -rw-r--r-- | slicer/test/Jamfile.jam | 1 | ||||
| -rw-r--r-- | slicer/test/initial/attributemap.xml | 6 | ||||
| -rw-r--r-- | slicer/test/initial/elementmap.xml | 14 | ||||
| -rw-r--r-- | slicer/test/preprocessor.cpp | 2 | ||||
| -rw-r--r-- | slicer/test/serializers.cpp | 35 | ||||
| -rw-r--r-- | slicer/test/xml.ice | 10 | ||||
| -rw-r--r-- | slicer/xml/serializer.cpp | 118 | ||||
| -rw-r--r-- | slicer/xml/serializer.h | 6 | 
8 files changed, 173 insertions, 19 deletions
diff --git a/slicer/test/Jamfile.jam b/slicer/test/Jamfile.jam index 4046e6f..53a9489 100644 --- a/slicer/test/Jamfile.jam +++ b/slicer/test/Jamfile.jam @@ -64,6 +64,7 @@ run preprocessor.cpp  	<library>adhocutil  	<include>..  	<library>../tool//slicer-compiler +	<dependency>types  	:  	preprocess  	; diff --git a/slicer/test/initial/attributemap.xml b/slicer/test/initial/attributemap.xml new file mode 100644 index 0000000..7651ac6 --- /dev/null +++ b/slicer/test/initial/attributemap.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Maps> +  <amap a="one" b="two" c="three"/> +	<emap/> +	<rmap/> +</Maps> diff --git a/slicer/test/initial/elementmap.xml b/slicer/test/initial/elementmap.xml new file mode 100644 index 0000000..1f8d913 --- /dev/null +++ b/slicer/test/initial/elementmap.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Maps> +  <amap/> +	<emap> +		<a>one</a> +		<b>two</b> +		<c>three</c> +	</emap> +	<rmap> +		<a Id="1">one</a> +		<b Id="2">two</b> +		<c Id="3">three</c> +	</rmap> +</Maps> diff --git a/slicer/test/preprocessor.cpp b/slicer/test/preprocessor.cpp index 7431a2d..cd2cd8d 100644 --- a/slicer/test/preprocessor.cpp +++ b/slicer/test/preprocessor.cpp @@ -20,7 +20,7 @@ ComponentsCount COMPONENTS_IN_TEST_ICE = {  	{ "inheritance.ice", 12 },  	{ "interfaces.ice", 0 },  	{ "json.ice", 2 }, -	{ "xml.ice", 2 }, +	{ "xml.ice", 5 },  	{ "db.ice", 4 },  	{ "types.ice", 3 }  }; diff --git a/slicer/test/serializers.cpp b/slicer/test/serializers.cpp index 6218b3b..350d570 100644 --- a/slicer/test/serializers.cpp +++ b/slicer/test/serializers.cpp @@ -254,6 +254,31 @@ checkSomeNumbers(const TestModule::SomeNumbers & sn)  }  void +attributeMap(const TestXml::Maps & s) +{ +	BOOST_REQUIRE_EQUAL(3, s.amap.size()); +	BOOST_REQUIRE_EQUAL("one", s.amap.find("a")->second); +	BOOST_REQUIRE_EQUAL("two", s.amap.find("b")->second); +	BOOST_REQUIRE_EQUAL("three", s.amap.find("c")->second); +} + +void +elementMap(const TestXml::Maps & s) +{ +	BOOST_REQUIRE_EQUAL(3, s.emap.size()); +	BOOST_REQUIRE_EQUAL("one", s.emap.find("a")->second); +	BOOST_REQUIRE_EQUAL("two", s.emap.find("b")->second); +	BOOST_REQUIRE_EQUAL("three", s.emap.find("c")->second); +	BOOST_REQUIRE_EQUAL(3, s.rmap.size()); +	BOOST_REQUIRE_EQUAL(1, s.rmap.find("a")->second.Id); +	BOOST_REQUIRE_EQUAL(2, s.rmap.find("b")->second.Id); +	BOOST_REQUIRE_EQUAL(3, s.rmap.find("c")->second.Id); +	BOOST_REQUIRE_EQUAL("one", s.rmap.find("a")->second.Name); +	BOOST_REQUIRE_EQUAL("two", s.rmap.find("b")->second.Name); +	BOOST_REQUIRE_EQUAL("three", s.rmap.find("c")->second.Name); +} + +void  checkObjectMap(const TestJson::Properties & p)  {  	BOOST_REQUIRE_EQUAL(3, p.size()); @@ -437,6 +462,16 @@ BOOST_AUTO_TEST_CASE( xml_rootEnums_xml )  	verifyByFile<TestModule::SomeNumbers, Slicer::XmlFileDeserializer>("enum.xml", checkSomeNumbers);  } +BOOST_AUTO_TEST_CASE( xml_attributemap_xml ) +{ +	verifyByFile<TestXml::Maps, Slicer::XmlFileDeserializer>("attributemap.xml", attributeMap); +} + +BOOST_AUTO_TEST_CASE( xml_elementmap_xml ) +{ +	verifyByFile<TestXml::Maps, Slicer::XmlFileDeserializer>("elementmap.xml", elementMap); +} +  BOOST_AUTO_TEST_CASE( json_rootEnums_json )  {  	verifyByFile<TestModule::SomeNumbers, Slicer::JsonFileDeserializer>("enum2.json", checkSomeNumbers); diff --git a/slicer/test/xml.ice b/slicer/test/xml.ice index ecb50b5..6deb02f 100644 --- a/slicer/test/xml.ice +++ b/slicer/test/xml.ice @@ -16,6 +16,16 @@ module TestXml {  		[ "slicer:xml:text" ]  		string Name;  	}; +	dictionary<string, string> StringMap; +	dictionary<string, EntityRef> RefMap; +	struct Maps { +		[ "slicer:xml:attributes" ] +		StringMap amap; +		[ "slicer:xml:elements" ] +		StringMap emap; +		[ "slicer:xml:elements" ] +		RefMap rmap; +	};  };  #endif diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 654793c..307819a 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -19,6 +19,10 @@ namespace Slicer {  	const std::string md_attribute = "xml:attribute";  	const std::string md_text = "xml:text";  	const std::string md_bare = "xml:bare"; +	const std::string md_attributes = "xml:attributes"; +	const std::string md_elements = "xml:elements"; +	const std::string keyName = "key"; +	const std::string valueName = "value";  	const auto defaultElementCreator = boost::bind(&xmlpp::Element::add_child, _1, _2, Glib::ustring());  	static const Glib::ustring TrueText("true"); @@ -171,6 +175,75 @@ namespace Slicer {  	};  	void +	XmlDeserializer::DocumentTreeIterateDictAttrs(const xmlpp::Element::AttributeList & attrs, ModelPartPtr dict) +	{ +		for (const auto & attr : attrs) { +			auto emp = dict->GetAnonChild(); +			emp->Create(); +			auto key = emp->GetChild(keyName); +			auto value = emp->GetChild(valueName); +			key->SetValue(new XmlValueSource(attr->get_name())); +			key->Complete(); +			value->SetValue(new XmlValueSource(attr->get_value())); +			value->Complete(); +			emp->Complete(); +		} +	} + +	void +	XmlDeserializer::DocumentTreeIterateDictElements(const xmlpp::Element * element, ModelPartPtr dict) +	{ +		auto node = element->get_first_child(); +		while (node) { +			if (auto element = dynamic_cast<const xmlpp::Element *>(node)) { +				auto emp = dict->GetAnonChild(); +				emp->Create(); +				auto key = emp->GetChild(keyName); +				auto value = emp->GetChildRef(valueName); +				key->SetValue(new XmlValueSource(element->get_name())); +				key->Complete(); +				DocumentTreeIterateElement(element, value->Child(), value); +				emp->Complete(); +			} +			node = node->get_next_sibling(); +		} +	} + +	void +	XmlDeserializer::DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartPtr smp, ChildRefPtr smpr) +	{ +		if (auto typeIdPropName = smp->GetTypeIdProperty()) { +			if (auto typeAttr = element->get_attribute(*typeIdPropName)) { +				smp = smp->GetSubclassModelPart(typeAttr->get_value()); +			} +		} +		smp->Create(); +		if (metaDataFlagSet(smpr->ChildMetaData(), md_attributes)) { +			auto attrs(element->get_attributes()); +			if (!attrs.empty()) { +				DocumentTreeIterateDictAttrs(attrs, smp); +			} +		} +		else if (metaDataFlagSet(smpr->ChildMetaData(), md_elements)) { +			DocumentTreeIterateDictElements(element, smp); +		} +		else { +			auto attrs(element->get_attributes()); +			if (!attrs.empty()) { +				DocumentTreeIterate(attrs.front(), smp); +			} +			auto firstChild = element->get_first_child(); +			if (firstChild) { +				DocumentTreeIterate(firstChild, smp); +			} +			else { +				smp->SetValue(new XmlContentValueSource()); +			} +		} +		smp->Complete(); +	} + +	void  	XmlDeserializer::DocumentTreeIterate(const xmlpp::Node * node, ModelPartPtr mp)  	{  		while (node) { @@ -183,24 +256,7 @@ namespace Slicer {  						smp = smp->GetAnonChild();  					}  					if (smp) { -						if (auto typeIdPropName = smp->GetTypeIdProperty()) { -							if (auto typeAttr = element->get_attribute(*typeIdPropName)) { -								smp = smp->GetSubclassModelPart(typeAttr->get_value()); -							} -						} -						smp->Create(); -						auto attrs(element->get_attributes()); -						if (!attrs.empty()) { -							DocumentTreeIterate(attrs.front(), smp); -						} -						auto firstChild = element->get_first_child(); -						if (firstChild) { -							DocumentTreeIterate(firstChild, smp); -						} -						else { -							smp->SetValue(new XmlContentValueSource()); -						} -						smp->Complete(); +						DocumentTreeIterateElement(element, smp, smpr);  					}  				}  			} @@ -247,6 +303,12 @@ namespace Slicer {  		else if (hp && metaDataFlagSet(hp->GetMetadata(), md_text)) {  			mp->GetValue(new XmlContentValueTarget(n));  		} +		else if (hp && metaDataFlagSet(hp->GetMetadata(), md_attributes)) { +			ModelTreeIterateDictAttrs(n->add_child(name), mp); +		} +		else if (hp && metaDataFlagSet(hp->GetMetadata(), md_elements)) { +			ModelTreeIterateDictElements(n->add_child(name), mp); +		}  		else {  			if (hp && metaDataFlagSet(hp->GetMetadata(), md_bare)) {  				ModelTreeProcessElement(n, mp, boost::bind(&xmlpp::Element::add_child, _1, name, Glib::ustring())); @@ -258,6 +320,26 @@ namespace Slicer {  	}  	void +	XmlSerializer::ModelTreeIterateDictAttrs(xmlpp::Element * element, ModelPartPtr dict) +	{ +		dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { +			mp->GetChild(keyName)->GetValue(new XmlValueTarget([&mp,element](const auto & name) { +				mp->GetChild(valueName)->GetValue(new XmlAttributeValueTarget(element, name)); +			})); +		}); +	} + +	void +	XmlSerializer::ModelTreeIterateDictElements(xmlpp::Element * element, ModelPartPtr dict) +	{ +		dict->OnEachChild([element](const auto &, const auto & mp, const auto &) { +			mp->GetChild(keyName)->GetValue(new XmlValueTarget([&mp,element](const auto & name) { +				ModelTreeProcessElement(element->add_child(name), mp->GetChild(valueName), defaultElementCreator); +			})); +		}); +	} + +	void  	XmlSerializer::ModelTreeProcessElement(xmlpp::Element * element, ModelPartPtr mp, const ElementCreator & ec)  	{  		auto typeIdPropName = mp->GetTypeIdProperty(); diff --git a/slicer/xml/serializer.h b/slicer/xml/serializer.h index 23ba17a..5b56ad1 100644 --- a/slicer/xml/serializer.h +++ b/slicer/xml/serializer.h @@ -3,6 +3,7 @@  #include <slicer/serializer.h>  #include <libxml++/document.h> +#include <libxml++/nodes/element.h>  #include <visibility.h>  namespace Slicer { @@ -14,6 +15,8 @@ namespace Slicer {  		protected:  			static void ModelTreeProcessElement(xmlpp::Element * n, ModelPartPtr mp, const ElementCreator &); +			static void ModelTreeIterateDictAttrs(xmlpp::Element * element, ModelPartPtr dict); +			static void ModelTreeIterateDictElements(xmlpp::Element * element, ModelPartPtr dict);  	};  	class DLL_PUBLIC XmlStreamSerializer : public XmlSerializer { @@ -49,7 +52,10 @@ namespace Slicer {  	class DLL_PUBLIC XmlDeserializer : public Deserializer {  		protected:  			static void DocumentTreeIterate(const xmlpp::Node * node, ModelPartPtr mp); +			static void DocumentTreeIterateElement(const xmlpp::Element * element, ModelPartPtr mp, ChildRefPtr c);  			static void DocumentTreeIterate(const xmlpp::Document * doc, ModelPartPtr mp); +			static void DocumentTreeIterateDictAttrs(const xmlpp::Element::AttributeList & attrs, ModelPartPtr dict); +			static void DocumentTreeIterateDictElements(const xmlpp::Element * parent, ModelPartPtr dict);  	};  	class DLL_PUBLIC XmlStreamDeserializer : public XmlDeserializer {  | 
