[gxml] * make deserialization handle enums, objects, as well as the other primitive types; better error han



commit 5fbbe2b3173367bcd2754e8921d216dc9853aff8
Author: Richard Schwarting <aquarichy gmail com>
Date:   Fri Jul 6 02:42:46 2012 -0400

    * make deserialization handle enums, objects, as well as the other primitive types; better error handling via ParamSpecs

 gxml/XmlSerializable.vala |  108 ++++++++++++++++++++++++++++----------------
 1 files changed, 69 insertions(+), 39 deletions(-)
---
diff --git a/gxml/XmlSerializable.vala b/gxml/XmlSerializable.vala
index b256116..541a7b8 100644
--- a/gxml/XmlSerializable.vala
+++ b/gxml/XmlSerializable.vala
@@ -151,7 +151,6 @@ namespace GXmlDom {
 
 		public GLib.Object deserialize_object (XNode node) throws SerializationError {
 			Element obj_elem;
-			NodeList properties;
 
 			string otype;
 			Type type;
@@ -171,52 +170,83 @@ namespace GXmlDom {
 			}
 
 			// Get the list of properties as ParamSpecs
-			obj = Object.newv (type, new Parameter[] {});
+			obj = Object.newv (type, new Parameter[] {}); // TODO: causes problems with Enums when 0 isn't a valid enum value (e.g. starts from 2 or something)
 			obj_class = obj.get_class ();
 			specs = obj_class.list_properties ();
 
-			properties = obj_elem.get_elements_by_tag_name ("Property");
-
-			for (int i = 0; i < properties.length; i++) {
-				Element prop_elem;
-				string pname;
-				string ptype;
-				Value val;
-
-				prop_elem = (Element)properties.nth (i);
-				pname = prop_elem.get_attribute ("pname");
-				ptype = prop_elem.get_attribute ("ptype"); // optional
-
-				// Check name and type for property
-				property_found = false;
-				foreach (ParamSpec spec in specs) {
-					if (spec.name == pname) {
-						// only doing this if ptype omitted
-						// want ptype shown in XML for readability?
-						type = spec.value_type;
-						property_found = true;
+			foreach (XNode child_node in obj_elem.child_nodes) {
+				if (child_node.node_name == "Property") {
+					Element prop_elem;
+					string pname;
+					string ptype;
+					Value val;
+
+					prop_elem = (Element)child_node;
+					pname = prop_elem.get_attribute ("pname");
+					ptype = prop_elem.get_attribute ("ptype"); // optional
+
+					// Check name and type for property
+					ParamSpec? spec = null;
+					for (int i = 0; i < specs.length; i++) {
+						if (specs[i].name == pname) {
+							// only doing this if ptype omitted
+							// want ptype shown in XML for readability?
+							spec = specs[i];
+							break;
+						}
 					}
-				}
-				if (!property_found) {
-					throw new SerializationError.UNKNOWN_PROPERTY ("Deserializing object of type '%s' claimed unknown property named '%s'", otype, pname);
-				}
 
-				if (false || ptype != "") {
-					// TODO: undisable if we support fields at some point
-					type = Type.from_name (ptype);
-					if (type == 0) {
-						/* This probably shouldn't happen while we're using
-						   ParamSpecs but if we support non-property fields
-						   later, it might be necessary again :D */
-						throw new SerializationError.UNKNOWN_TYPE ("Deserializing object '%s' has property '%s' with unknown type '%s'", otype, pname, ptype);
+					if (spec == null) {
+						throw new SerializationError.UNKNOWN_PROPERTY ("Deserializing object of type '%s' claimed unknown property named '%s'\nXML [%s]", otype, pname, obj_elem.to_string ());
+					}
+
+					type = spec.value_type;
+
+					if (false || ptype != "") {
+						// TODO: undisable if we support fields at some point
+						type = Type.from_name (ptype);
+						if (type == 0) {
+							/* This probably shouldn't happen while we're using
+							   ParamSpecs but if we support non-property fields
+							   later, it might be necessary again :D */
+							throw new SerializationError.UNKNOWN_TYPE ("Deserializing object '%s' has property '%s' with unknown type '%s'", otype, pname, ptype);
+						}
 					}
-				}
 
-				// Get value and save this all as a parameter
-				val = Value (type);
-				string_to_gvalue (prop_elem.content, ref val);
+					// Get value and save this all as a parameter
+					bool transformable = false;
+					bool transformed = false;
+					val = Value (type);
+					if (GLib.Value.type_transformable (type, typeof (string))) {
+						transformable = true;
+
+						try {
+							string_to_gvalue (prop_elem.content, ref val);
+							transformed = true;
+						} catch (SerializationError e) {
+						}
+						// } else if (type.is_a (typeof (Gee.Collection))) {
+					} else if (type.is_a (typeof (GLib.Object))) {
+						GXmlDom.XNode prop_elem_child;
+						Object property_object;
+
+						try {
+							prop_elem_child = prop_elem.first_child;
+							property_object = this.deserialize_object (prop_elem_child);
+							val.set_object (property_object);
+							transformed = true;
+						} catch (GXmlDom.SerializationError e) {
+							e.message += "\nXML [%s]".printf (prop_elem.to_string ());
+							throw e;
+						}
+					}
 
-				obj.set_property (pname, val);
+					if (transformed == false) {
+						throw new SerializationError.UNSUPPORTED_TYPE ("Cannot deserialize type '%s/%s' for property '%s' of object '%s'\nXML [%s] %s", type.name (), type.to_string (), pname, otype, obj_elem.to_string (), (transformable ? "though it is transformable" : ""));
+					}
+
+					obj.set_property (pname, val);
+				}
 			}
 
 			return obj;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]