[gxml/serialization] All tests PASS for SerializableJson. Serialization API changes * Serializable has gained a protected



commit 3cf7e60f4ff11c4534fafce6870cbe2452c5a081
Author: Daniel Espinosa <esodan gmail com>
Date:   Thu Oct 17 16:39:22 2013 -0500

    All tests PASS for SerializableJson. Serialization API changes
    * Serializable has gained a protected properties property
      to be used by derived classes to save on demand lists of
      serializable properties
    * Serializable provides both abstract and virtual methods. Virtual
      methods have a default implementation to be used by implementators
      allowing to override on derived classes of implementators
    * Serializable implementators must implement abstract methods but if
      they want to derived classes to override them, they must be declared
      as virtual
    * SerializableJson has been ported to Serializable. Implements most
      mothods and reuse most of them with default implementation and
      declared as virtual in order to allow to be overriden on derived
      classes.
    * All Unit Tests for SerializableJson has been ported to Serializable
      and new SerializableJson and finish with PASS state.
    * SerializableObjectModel has been ported to Serializable. No tests
      yet.

 gxml/Serializable.vala            |   73 ++++++++++++----------
 gxml/SerializableJson.vala        |  109 ++++++++++++++++++++-------------
 gxml/SerializableObjectModel.vala |   32 +++++++++-
 gxml/Serialization.vala           |   36 ++++++++---
 test/SerializableTest.vala        |  123 +++++++++++++++----------------------
 test/SerializationTest.vala       |   65 +++++++++++--------
 6 files changed, 250 insertions(+), 188 deletions(-)
---
diff --git a/gxml/Serializable.vala b/gxml/Serializable.vala
index 3248f87..db43c66 100644
--- a/gxml/Serializable.vala
+++ b/gxml/Serializable.vala
@@ -71,6 +71,7 @@ namespace GXml {
         * For an example, look in tests/XmlSerializableTest
         */
        public interface Serializable : GLib.Object {
+               protected abstract ParamSpec[] properties { get; set; }
                /**
                 * Defines the way to set Node name.
                 *
@@ -127,6 +128,10 @@ namespace GXml {
                 * this method.  If the method returns %NULL,
                 * { link GXml.Serialization} will attempt handle it itsel.
                 *
+                * Implementors:
+                * Use Serializable.get_property_value in order to allow derived classes to
+                * override the properties to serialize.
+                *
                 * @param property_name string name of a property to serialize.
                 * @param spec the { link GLib.ParamSpec} describing the property.
                 * @param doc the { link GXml.Document} the returned { link GXml.Node} should belong to
@@ -156,6 +161,10 @@ namespace GXml {
                 * as simple as a { link GXml.Text} that stores the data as a
                 * string.
                 *
+                * Implementors:
+                * Use Serializable.get_property_value in order to allow derived classes to
+                * override the properties to serialize.
+                *
                 * @param property_name the name of the property as a string
                 * @param spec the { link GLib.ParamSpec} describing the property.
                 * @param property_node the { link GXml.Node} encapsulating data to deserialize
@@ -165,7 +174,8 @@ namespace GXml {
                                                          throws Error;
 
                /**
-                * Signal to serialize unknown properties.
+                * Signal to serialize unknown properties. Any new node must be added to
+                * @element before return the new @node added.
                 * 
                 * @element a { link GXml.Node} to add attribute or child nodes to
                 * @prop a { link GLib.ParamSpec} describing attribute to serialize
@@ -174,7 +184,8 @@ namespace GXml {
                public signal void serialize_unknown_property (Node element, ParamSpec prop, out Node node);
 
                /**
-                * Signal to serialize unknown properties.
+                * Signal to serialize unknown properties. Any new node must be added to
+                * @element before return the new @node added.
                 * 
                 * @element a { link GXml.Node} to add attribute or child nodes to
                 * @prop a { link GLib.ParamSpec} describing attribute to serialize
@@ -225,13 +236,16 @@ namespace GXml {
                 * { link GLib.ParamSpec} s separately, rather than creating new
                 * ones for each call.
                 */
-               public virtual GLib.ParamSpec? find_property_spec (string property_name) {
+               public abstract GLib.ParamSpec? find_property_spec (string property_name);
+
+               public virtual GLib.ParamSpec? default_find_property_spec (string property_name) {
                        init_properties ();
-                       string pn = property_name.down ();
-                       if (ignored_serializable_properties.contains (pn)) {
-                               return null;
+                       var props = list_serializable_properties ();
+                       foreach (ParamSpec spec in props) {
+                               if (spec.name.down () == property_name.down ())
+                                       return spec;
                        }
-                       return get_class ().find_property (pn);
+                       return null;
                }
 
                /**
@@ -240,7 +254,9 @@ namespace GXml {
                 * is not required to be called at class implementor's construction time.
                 *
                 */
-               public virtual void init_properties ()
+               public abstract void init_properties ();
+
+               public virtual void default_init_properties ()
                {
                        if (ignored_serializable_properties == null) {
                                ignored_serializable_properties = new HashTable<string,ParamSpec> (str_hash, 
str_equal);
@@ -288,16 +304,21 @@ namespace GXml {
                 * { link GLib.ParamSpec} s separately, rather than creating new
                 * ones for each call.
                 */
-               public virtual GLib.ParamSpec[] list_serializable_properties ()
+               public abstract GLib.ParamSpec[] list_serializable_properties ();
+
+               public virtual GLib.ParamSpec[] default_list_serializable_properties ()
                {
                        init_properties ();
-                       ParamSpec[] props = {};
-                       foreach (ParamSpec spec in this.get_class ().list_properties ()) {
-                               if (!ignored_serializable_properties.contains (spec.name)) {
-                                       props += spec;
+                       if (properties == null) {
+                               ParamSpec[] props = {};
+                               foreach (ParamSpec spec in this.get_class ().list_properties ()) {
+                                       if (!ignored_serializable_properties.contains (spec.name)) {
+                                               props += spec;
+                                       }
                                }
+                               properties = props;
                        }
-                       return props;
+                       return properties;
                }
 
                /*
@@ -322,27 +343,13 @@ namespace GXml {
                 * by the other { link GXml.Serializable} functions.
                 *
                 * `spec` is usually obtained from list_properties or find_property.
-                *
-                * As indicated by its name, `str_value` is a { link GLib.Value}
-                * that wants to hold a string type.
-                *
-                * @todo: why not just return a string? :D Who cares
-                * how analogous it is to { link GLib.Object.get_property}? :D
                 */
-               public virtual string get_property_value (GLib.ParamSpec spec) 
+               public abstract void get_property_value (GLib.ParamSpec spec, ref Value val);
+
+               public virtual void default_get_property_value (GLib.ParamSpec spec, ref Value val) 
                {
-                       Value val = Value (spec.value_type);
                        if (!ignored_serializable_properties.contains (spec.name))
-                       {
-                               Value ret = "";
                                ((GLib.Object)this).get_property (spec.name, ref val);
-                               if (Value.type_transformable (val.type (), typeof (string)))
-                               {
-                                       val.transform (ref ret);
-                                       return ret.dup_string ();
-                               }
-                       }
-                       return "";
                }
                /*
                 * Set a property's value.
@@ -366,7 +373,9 @@ namespace GXml {
                 * handle this case as a virtual property, supported
                 * by the other { link GXml.Serializable} functions.
                 */
-               public virtual void set_property_value (GLib.ParamSpec spec, GLib.Value val)
+               public abstract void set_property_value (GLib.ParamSpec spec, GLib.Value val);
+
+               public virtual void default_set_property_value (GLib.ParamSpec spec, GLib.Value val)
                {
                        if (!ignored_serializable_properties.contains (spec.name)) {
                                ((GLib.Object)this).set_property (spec.name, val);
diff --git a/gxml/SerializableJson.vala b/gxml/SerializableJson.vala
index 045678d..3bd6023 100644
--- a/gxml/SerializableJson.vala
+++ b/gxml/SerializableJson.vala
@@ -35,6 +35,7 @@
 public class GXml.SerializableJson : GLib.Object, Serializable
 {
        /* Serializable Interface properties */
+       protected ParamSpec[] properties { get; set; }
        public string serializable_node_name { get; protected set; }
        public bool serializable_property_use_nick { get; set; }
        public HashTable<string,GLib.ParamSpec>  ignored_serializable_properties { get; protected set; }
@@ -42,6 +43,31 @@ public class GXml.SerializableJson : GLib.Object, Serializable
 
        public string?  serialized_xml_node_value { get; protected set; default = null; }
 
+       public virtual GLib.ParamSpec? find_property_spec (string property_name)
+       {
+               return default_find_property_spec (property_name);
+       }
+
+       public virtual void init_properties ()
+       {
+               default_init_properties ();
+       }
+
+       public virtual GLib.ParamSpec[] list_serializable_properties ()
+       {
+               return default_list_serializable_properties ();
+       }
+
+       public virtual void get_property_value (GLib.ParamSpec spec, ref Value val)
+       {
+               default_get_property_value (spec, ref val);
+       }
+
+       public virtual void set_property_value (GLib.ParamSpec spec, GLib.Value val)
+       {
+               default_set_property_value (spec, val);
+       }
+
   /**
    * If @node is a Document serialize just add an <Object> element.
    *
@@ -54,9 +80,7 @@ public class GXml.SerializableJson : GLib.Object, Serializable
        {
                Document doc;
                Element root;
-               ParamSpec[] prop_specs;
-               Element prop;
-               Node value_prop = null;
+               ParamSpec[] props;
                string oid = "%p".printf(this);
 
                if (node is Document)
@@ -68,56 +92,59 @@ public class GXml.SerializableJson : GLib.Object, Serializable
                doc.append_child (root);
                root.set_attribute ("otype", this.get_type ().name ());
                root.set_attribute ("oid", oid);
-
-               prop_specs = list_serializable_properties ();
-
-               foreach (ParamSpec prop_spec in prop_specs) {
-                       prop = doc.create_element ("Property");
-                       prop.set_attribute ("ptype", prop_spec.value_type.name ());
-                       prop.set_attribute ("pname", prop_spec.name);
-                       value_prop = serialize_property (prop, prop_spec);
-                       prop.append_child (value_prop);
-                       root.append_child (prop);
+               props = list_serializable_properties ();
+               foreach (ParamSpec prop_spec in props) {
+                       serialize_property (root, prop_spec);
                }
                return root;
        }
 
-       public GXml.Node? serialize_property (Element element, 
+       public virtual GXml.Node? serialize_property (Element element, 
                                              GLib.ParamSpec prop)
                                              throws Error
        {
                Type type;
-               Value value;
+               Value val;
                Node value_node = null;
                Element prop_node;
 
                type = prop.value_type;
 
                if (type.is_a (typeof (Serializable))) {
-                       value = Value (type);
-                       this.get_property (prop.name, ref value);
-                       return ((Serializable)value.get_object ()).serialize (element);
+                       val = Value (type);
+                       this.get_property_value (prop, ref val);
+                       return ((Serializable) val.get_object ()).serialize (element);
                }
 
                var doc = element.owner_document;
                prop_node = doc.create_element ("Property");
                prop_node.set_attribute ("ptype", prop.value_type.name ());
                prop_node.set_attribute ("pname", prop.name);
+               element.append_child (prop_node);
 
                if (type.is_enum ())
                {
-                       value = Value (typeof (int));
-                       this.get_property (prop.name, ref value);
-                       value_node = doc.create_text_node ("%d".printf (value.get_int ()));
+                       val = Value (typeof (int));
+                       this.get_property_value (prop, ref val);
+                       value_node = doc.create_text_node ("%d".printf (val.get_int ()));
+                       prop_node.append_child (value_node);
+                       return prop_node;
                } 
                else if (Value.type_transformable (type, typeof (string))) 
                { // e.g. int, double, string, bool
-                       value = Value (typeof (string));
-                       this.get_property (prop.name, ref value);
-                       value_node = doc.create_text_node (value.get_string ());
+//             GLib.message ("DEBUG: Transforming property  name '%s' of object '%s', using GLib defaults", 
prop.name, this.get_type ().name ());
+                       val = Value (type);
+                       Value t = Value (typeof (string));
+                       this.get_property_value (prop, ref val);
+                       val.transform (ref t);
+                       value_node = doc.create_text_node (t.get_string ());
+                       prop_node.append_child (value_node);
+                       return prop_node;
                }
                else if (type == typeof (GLib.Type)) {
                        value_node = doc.create_text_node (type.name ());
+                       prop_node.append_child (value_node);
+                       return prop_node;
                }
                else if (type.is_a (typeof (GLib.Object))
                           && ! type.is_a (typeof (Gee.Collection)))
@@ -125,21 +152,17 @@ public class GXml.SerializableJson : GLib.Object, Serializable
                        GLib.Object child_object;
 
                        // TODO: this is going to get complicated
-                       value = Value (typeof (GLib.Object));
-                       this.get_property (prop.name, ref value);
-                       child_object = value.get_object ();
+                       val = Value (typeof (GLib.Object));
+                       this.get_property_value (prop, ref val);
+                       child_object = val.get_object ();
                        Document value_doc = Serialization.serialize_object (child_object);
-
                        value_node = doc.copy_node (value_doc.document_element);
+                       prop_node.append_child (value_node);
+                       return prop_node;
                }
-               else if (type.name () == "gpointer") {
-                       GLib.warning ("DEBUG: skipping gpointer with name '%s' of object '%s'", prop.name, 
this.get_type ().name ());
-                       value_node = doc.create_text_node (prop.name);
-               } else {
-                       throw new SerializationError.UNSUPPORTED_TYPE ("Can't currently serialize type '%s' 
for property '%s' of object '%s'", type.name (), prop.name, this.get_type ().name ());
-               }
-
-               return value_node;
+               //GLib.message ("DEBUG: serialing unknown property type '%s' of object '%s'", prop.name, 
this.get_type ().name ());
+               serialize_unknown_property_type (prop_node, prop, out value_node);
+               return prop_node;
        }
 
        public Node? deserialize (Node node) throws Error
@@ -162,13 +185,14 @@ public class GXml.SerializableJson : GLib.Object, Serializable
                return obj_elem;
        }
 
-       public bool deserialize_property (GXml.Node property_node) throws Error
+       public virtual bool deserialize_property (GXml.Node property_node) throws Error
        {
+               //GLib.message ("At SerializableJson.deserialize_property");
                if (property_node.node_name == "Property")
                {
                        Element prop_elem;
                        string pname;
-                       string otype;
+                       string ptype;
                        Type type;
                        Value val;
                        ParamSpec spec;
@@ -176,15 +200,13 @@ public class GXml.SerializableJson : GLib.Object, Serializable
 
                        prop_elem = (Element)property_node;
                        pname = prop_elem.get_attribute ("pname");
-                       otype = prop_elem.get_attribute ("otype");
-                       type = Type.from_name (otype);
-                       //ptype = prop_elem.get_attribute ("ptype"); // optional
-
+                       ptype = prop_elem.get_attribute ("ptype");
+                       type = Type.from_name (ptype);
                        // Check name and type for property
                        spec = this.find_property_spec (pname);
 
                        if (spec == null) {
-                               GLib.message ("Deserializing object of type '%s' claimed unknown property 
named '%s'\nXML [%s]", otype, pname, property_node.to_string ());
+                               GLib.message ("Deserializing object of type '%s' claimed unknown property 
named '%s'\nXML [%s]", ptype, pname, property_node.to_string ());
                                unknown_serializable_property.set (property_node.node_name, property_node);
                        }
                        else {
@@ -199,6 +221,7 @@ public class GXml.SerializableJson : GLib.Object, Serializable
                                        if (GLib.Value.type_transformable (type, typeof (string))) {
                                                Serializable.string_to_gvalue (prop_elem.content, ref val);
                                                this.set_property_value (spec, val);
+                                               //GLib.message (@"Setting value to property $(spec.name)");
                                        }
                                        else if (type.is_a (typeof (GLib.Object))) 
                                        {
diff --git a/gxml/SerializableObjectModel.vala b/gxml/SerializableObjectModel.vala
index c5ef31a..9f2b89a 100644
--- a/gxml/SerializableObjectModel.vala
+++ b/gxml/SerializableObjectModel.vala
@@ -23,6 +23,7 @@
 public abstract class GXml.SerializableObjectModel : Object, Serializable
 {
        /* Serializable interface properties */
+       protected ParamSpec[] properties { get; set; }
        public GLib.HashTable<string,GLib.ParamSpec> ignored_serializable_properties { get; protected set; }
        public bool serializable_property_use_nick { get; set; }
        public string? serialized_xml_node_value { get; protected set; default=null; }
@@ -36,6 +37,31 @@ public abstract class GXml.SerializableObjectModel : Object, Serializable
                serializable_node_name = get_type().name().down();
        }
 
+       public virtual GLib.ParamSpec? find_property_spec (string property_name)
+       {
+               return default_find_property_spec (property_name);
+       }
+
+       public virtual void init_properties ()
+       {
+               default_init_properties ();
+       }
+
+       public virtual GLib.ParamSpec[] list_serializable_properties ()
+       {
+               return default_list_serializable_properties ();
+       }
+
+       public virtual void get_property_value (GLib.ParamSpec spec, ref Value val)
+       {
+               default_get_property_value (spec, ref val);
+       }
+
+       public virtual void set_property_value (GLib.ParamSpec spec, GLib.Value val)
+       {
+               default_set_property_value (spec, val);
+       }
+
        public Node? serialize (Node node) throws Error
        {
                Document doc;
@@ -188,8 +214,10 @@ public abstract class GXml.SerializableObjectModel : Object, Serializable
                        foreach (ParamSpec p in alp) {
                                var bp = ((Serializable)b).find_property_spec (p.name);
                                if (bp != null) {
-                                       var apval = ((Serializable)a).get_property_value (p);
-                                       var bpval = ((Serializable)b).get_property_value (bp);
+                                       Value apval = Value (p.value_type);
+                                       ((Serializable)a).get_property_value (p, ref apval);
+                                       Value bpval = Value (bp.value_type);;
+                                       ((Serializable)b).get_property_value (bp, ref bpval);
                                        if ( apval != bpval)
                                                ret = false;
                                }
diff --git a/gxml/Serialization.vala b/gxml/Serialization.vala
index e7f1234..a0cdda5 100644
--- a/gxml/Serialization.vala
+++ b/gxml/Serialization.vala
@@ -48,11 +48,11 @@ namespace GXml {
         */
        public errordomain SerializationError {
                /**
-                * An object without a known { link GLib.Type} was encountered.
+                * An unknown { link GLib.Type} was encountered.
                 */
                UNKNOWN_TYPE,
                /**
-                * A property was described in XML that is not known to the object's type.
+                * A property was described in XML that is not known { link GLib.Type}.
                 */
                UNKNOWN_PROPERTY,
                /**
@@ -67,6 +67,10 @@ namespace GXml {
                 * Serialization/Deserialization is unsupported for given { link GLib.Type}
                 */
                UNSUPPORTED_TYPE,
+               /**
+                * Serialization/Deserialization is unsupported for given XML structure
+                */
+               UNSUPPORTED_FILE_FORMAT
        }
 
        /**
@@ -222,6 +226,10 @@ namespace GXml {
                        a separate document for it to already be a
                        part of as its owner_document. */
                        doc = new Document ();
+                       if (object is Serializable) {
+                               ((Serializable) object).serialize (doc);
+                               return doc;
+                       }
                        // If the object has been serialized before, let's not do it again!
                        oid = "%p".printf (object);
                        // first, check if its been serialised already, and if so, just return an ObjectRef 
element for it.
@@ -288,7 +296,6 @@ namespace GXml {
                        Type type;
                        type = spec.value_type;
                        // Get value and save this all as a parameter
-                       bool transformed = false;
                        val = Value (type);
                        if (GLib.Value.type_transformable (type, typeof (string))) {
                                        Serializable.string_to_gvalue (prop_elem.content, ref val);
@@ -345,17 +352,20 @@ namespace GXml {
                 * to the system deserializing them or a
                 * { link GXml.SerializationError} will result.
                 *
-                * @param node { link GXml.Node} representing a { link GLib.Object}
+                * @type object type to deserialize
+                * @doc a { link GXml.Document} to deseralize from
                 * @return the deserialized { link GLib.Object}
                 */
-               public static GLib.Object deserialize_object (GXml.Document doc) throws Error
+               public static GLib.Object deserialize_object (Type type, GXml.Document doc) throws Error
                {
-                       // FIXME: Use some heuristics to find the kind of serialization used
-                       //        or ADD A PARAMETER to define the method to use.
-                       //        This command use just GObject and JSON methods. No Serializable
-                       //        implementators are used.
+                       if (type.is_a (typeof (Serializable))) {
+                               Object object = Object.new (type);
+                               ((Serializable) object).deserialize (doc);
+                               return object;
+                       }
                        return deserialize_object_from_node (doc.document_element);
                }
+
                /**
                 * This function must assume deserialize over non-Serializable objects
                 * because Serializable have its own method serialize/deserialize
@@ -388,6 +398,12 @@ namespace GXml {
                        if (type == 0) {
                                throw new SerializationError.UNKNOWN_TYPE ("Deserializing unknown GType '%s' 
objects is unsupported", otype);
                        }
+                       
+                       if (type.is_a (typeof (Serializable))) {
+                               obj = Object.new (type);
+                               ((Serializable) obj).deserialize (obj_node);
+                               return obj;
+                       }
 
                        // Get the list of properties as ParamSpecs
                        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)
@@ -410,7 +426,7 @@ namespace GXml {
                                        spec = obj_class.find_property (pname);
 
                                        if (spec == null) {
-                                               throw new SerializationError.UNKNOWN_PROPERTY ("Deserializing 
property type '%s' for object type '%s' is unsupported-->XML: [%s]", pname, otype, obj_elem.to_string ());
+                                               throw new SerializationError.UNKNOWN_PROPERTY ("Unknown 
property '%s' found, for object type '%s'-->XML: [%s]", pname, otype, obj_elem.to_string ());
                                                return null;
                                        }
                                        Serialization.deserialize_property (spec, prop_elem, out val);
diff --git a/test/SerializableTest.vala b/test/SerializableTest.vala
index 34cb42c..5751939 100644
--- a/test/SerializableTest.vala
+++ b/test/SerializableTest.vala
@@ -47,7 +47,6 @@ public class SerializableTomato : GXml.SerializableJson {
                             a.age == b.age &&
                             a.height == b.height &&
                             a.description == b.description);
-
                return same;
        }
 }
@@ -72,56 +71,45 @@ public class SerializableCapsicum : GXml.SerializableJson {
                this.age = age;
                this.height = height;
                this.ratings = ratings;
+               ((Serializable)this).serialize_unknown_property_type.connect 
(serialize_unknown_property_type);
+               ((Serializable)this).deserialize_unknown_property_type.connect 
(deserialize_unknown_property_type);
        }
 
        /* TODO: do we really need GLib.Value? or should we modify the object directly?
           Want an example using GBoxed too
           Perhaps these shouldn't be object methods, perhaps they should be static?
           Can't have static methods in an interface :(, right? */
-       public bool deserialize_property (string property_name, /* out GLib.Value value, */
-                                         GLib.ParamSpec spec, GXml.Node property_node)  {
+       public void deserialize_unknown_property_type (GXml.Node element, ParamSpec prop)
+       {
                GLib.Value outvalue = GLib.Value (typeof (int));
-
-               switch (property_name) {
+               switch (prop.name) {
                case "ratings":
                        this.ratings = new GLib.List<int> ();
-                       foreach (GXml.Node rating in property_node.child_nodes) {
+                       foreach (GXml.Node rating in element.child_nodes) {
                                int64.try_parse (((GXml.Element)rating).content, out outvalue);
                                this.ratings.append ((int)outvalue.get_int64 ());
                        }
-                       return true;
-               case "height":
-                       int64.try_parse (((GXml.Element)property_node).content, out outvalue);
-                       this.height = (int)outvalue.get_int64 () - 1;
-                       return true;
+                       break;
                default:
-                       Test.message ("Wasn't expecting the SerializableCapsicum property '%s'", 
property_name);
+                       Test.message ("Wasn't expecting the SerializableCapsicum property '%s'", prop.name);
                        assert_not_reached ();
                }
-
-               return false;
        }
-       public GXml.Node? serialize_property (string property_name, /*GLib.Value value,*/ GLib.ParamSpec 
spec, GXml.Document doc) {
-               GXml.Element rating;
-
-               switch (property_name) {
+       private void serialize_unknown_property_type (GXml.Node element, ParamSpec prop, out GXml.Node node)
+       {
+               Document doc = element.owner_document;
+               switch (prop.name) {
                case "ratings":
-                       GXml.DocumentFragment frag = doc.create_document_fragment ();
                        foreach (int rating_int in ratings) {
-                               rating = doc.create_element ("rating");
-                               rating.content = "%d".printf (rating_int);
-                               frag.append_child (rating);
+                               Element n = doc.create_element ("rating");
+                               n.content = "%d".printf (rating_int);
+                               element.append_child (n);
                        }
-                       return frag;
-               case "height":
-                       return doc.create_text_node ("%d".printf (height + 1));
+                       break;
                default:
-                       Test.message ("Wasn't expecting the SerializableCapsicum property '%s'", 
property_name);
+                       Test.message ("Wasn't expecting the SerializableCapsicum property '%s'", prop.name);
                        assert_not_reached ();
                }
-
-               // returning null does a normal serialization
-               return null;
        }
 }
 
@@ -137,7 +125,6 @@ public class SerializableBanana : GXml.SerializableJson {
                this.public_field = public_field;
                this.private_property = private_property;
                this.public_property = public_property;
-
        }
 
        public string to_string () {
@@ -151,74 +138,63 @@ public class SerializableBanana : GXml.SerializableJson {
                        a.public_property == b.public_property);
        }
 
-       private ParamSpec[] properties = null;
-       public unowned GLib.ParamSpec[] list_properties () {
-               // TODO: so, if someone implements list_properties, but they don't create there array until 
called, that could be inefficient if they don't cache.  If they create it at construction, then serialising 
and deserialising will lose it?   offer guidance
-               if (this.properties == null) {
-                       properties = new ParamSpec[4];
+       
+       // This method overrides the one implemented at Serializable
+       public override GLib.ParamSpec[] list_serializable_properties ()
+       {
+               if (properties == null) {
+                       properties = new ParamSpec [4];
                        int i = 0;
                        foreach (string name in new string[] { "private-field", "public-field", 
"private-property", "public-property" }) {
-                               properties[i] = new ParamSpecInt (name, name, name, int.MIN, int.MAX, 0, 
ParamFlags.READABLE); // TODO: offer guidance for these fields, esp. ParamFlags
+                               // TODO: offer guidance for these fields, esp. ParamFlags
+                               properties[i] = (ParamSpec) new ParamSpecInt (name, name, name, int.MIN, 
int.MAX, 0, ParamFlags.READABLE); 
                                i++;
-                               // TODO: does serialisation use anything other than ParamSpec.name?
                        }
                }
-               return this.properties;
+               return properties;
        }
 
-       private GLib.ParamSpec prop;
-       public unowned GLib.ParamSpec? find_property (string property_name) {
-               GLib.ParamSpec[] properties = this.list_properties ();
-               foreach (ParamSpec prop in properties) {
-                       if (prop.name == property_name) {
-                               this.prop = prop;
-                               return this.prop;
-                       }
-               }
-               return null;
-       }
-
-       public new void get_property (GLib.ParamSpec spec, ref GLib.Value str_value) {
-               Value value = Value (typeof (int));
-
+       // This method overrides the one implemented at Serializable
+       public override void get_property_value (GLib.ParamSpec spec, ref Value val)
+       {
+               val = Value (typeof (int));
                switch (spec.name) {
                case "private-field":
-                       value.set_int (this.private_field);
+                       val.set_int (this.private_field);
                        break;
                case "public-field":
-                       value.set_int (this.public_field);
+                       val.set_int (this.public_field);
                        break;
                case "private-property":
-                       value.set_int (this.private_property);
+                       val.set_int (this.private_property);
                        break;
                case "public-property":
-                       value.set_int (this.public_property);
+                       val.set_int (this.public_property);
                        break;
                default:
-                       ((GLib.Object)this).get_property (spec.name, ref str_value);
+                       ((GLib.Object)this).get_property (spec.name, ref val);
                        return;
                }
-
-               value.transform (ref str_value);
-               return;
        }
 
-       public new void set_property (GLib.ParamSpec spec, GLib.Value value) {
+       // This method overrides the one implemented at Serializable
+       public override void set_property_value (GLib.ParamSpec spec, GLib.Value val)
+       {
                switch (spec.name) {
                case "private-field":
-                       this.private_field = value.get_int ();
+                       this.private_field = val.get_int ();
                        break;
                case "public-field":
-                       this.public_field = value.get_int ();
+                       this.public_field = val.get_int ();
                        break;
                case "private-property":
-                       this.private_property = value.get_int ();
+                       this.private_property = val.get_int ();
                        break;
                case "public-property":
-                       this.public_property = value.get_int ();
+                       this.public_property = val.get_int ();
                        break;
                default:
-                       ((GLib.Object)this).set_property (spec.name, value);
+                       ((GLib.Object)this).set_property (spec.name, val);
                        return;
                }
        }
@@ -247,11 +223,12 @@ class SerializableTest : GXmlTest {
                                ratings.append (13);
                                ratings.append (21);
 
-                               capsicum = new SerializableCapsicum (2, 3, 5, ratings);
+                               capsicum = new SerializableCapsicum (2, 3, 6, ratings);
                                try {
-                                       doc = Serialization.serialize_object (capsicum);
+                                       doc = new Document ();
+                                       capsicum.serialize (doc);
                                } catch (Error e) {
-                                       Test.message ("%s", e.message);
+                                       GLib.message ("%s", e.message);
                                        assert_not_reached ();
                                }
 
@@ -265,13 +242,13 @@ class SerializableTest : GXmlTest {
                                        }
 
                                        try {
-                                               capsicum_new = 
(SerializableCapsicum)Serialization.deserialize_object (doc);
+                                               capsicum_new = 
(SerializableCapsicum)Serialization.deserialize_object (typeof (SerializableCapsicum), doc);
                                        } catch (Error e) {
                                                Test.message ("%s", e.message);
                                                assert_not_reached ();
                                        }
-                                       if (capsicum_new.height != 5 || ratings.length () != 3 || 
ratings.nth_data (0) != 8 || ratings.nth_data (2) != 21) {
-                                               Test.message ("Did not deserialize as expected.  Got [%s] but 
expected height and ratings from [%s]", capsicum_new.to_string (), capsicum.to_string ());
+                                       if (capsicum_new.height != 6 || ratings.length () != 3 || 
ratings.nth_data (0) != 8 || ratings.nth_data (2) != 21) {
+                                               Test.message ("Did not deserialize as expected.  Got [%s] but 
expected height and ratings from [%s], length: %s", capsicum_new.to_string (), capsicum.to_string (), 
ratings.length ().to_string ());
                                                assert_not_reached ();
                                        }
                                } catch (RegexError e) {
diff --git a/test/SerializationTest.vala b/test/SerializationTest.vala
index f93bc03..5420103 100644
--- a/test/SerializationTest.vala
+++ b/test/SerializationTest.vala
@@ -251,9 +251,13 @@ public class RecursiveProperty : GLib.Object {
 class SerializationTest : GXmlTest {
        public delegate string StringifyFunc (GLib.Object object);
 
-       public static GLib.Object test_serialization_deserialization (GLib.Object object, string name, 
EqualFunc equals, StringifyFunc stringify) {
+       public static GLib.Object test_serialization_deserialization (GLib.Object object, 
+                                                                     string name,
+                                                                     EqualFunc equals,
+                                                                     StringifyFunc stringify)
+       {
                string xml_filename;
-               GXml.Node node;
+               GXml.Document sdoc;
                GXml.Document doc;
                GLib.Object object_new = null;
 
@@ -263,23 +267,22 @@ class SerializationTest : GXmlTest {
                xml_filename = "_serialization_test_" + name + ".xml";
 
                try {
-                       node = Serialization.serialize_object (object);
-
+                       sdoc = Serialization.serialize_object (object);
                        // TODO: assert that node is right
-                       node.owner_document.save_to_path (xml_filename);
+                       sdoc.save_to_path (xml_filename);
                        // TODO: assert that saved file is right
                        doc = new GXml.Document.from_path (xml_filename);
                        // TODO: assert that loaded file is right; do document compare with original
 
-                       object_new = Serialization.deserialize_object (doc);
+                       object_new = Serialization.deserialize_object (object.get_type (), doc);
 
                        if (! equals (object, object_new)) {
-                               Test.message ("Expected [%s] but got [%s]",
-                                             stringify (object), stringify (object_new));
+                               GLib.message ("Deserialization: Expected [%s] but got [%s] From XML: [[%s]]",
+                                             stringify (object), stringify (object_new), doc.to_string ());
                                assert_not_reached ();
                        }
                } catch (GLib.Error e) {
-                       Test.message ("%s", e.message);
+                       GLib.message ("%s", e.message);
                        assert_not_reached ();
                }
 
@@ -334,15 +337,15 @@ class SerializationTest : GXmlTest {
 
                                try {
                                        doc = new Document.from_string ("<Object otype='Fruit'><Property 
pname='age' ptype='gint'>3</Property></Object>");
-                                       fruit = (Fruit)Serialization.deserialize_object (doc);
+                                       fruit = (Fruit)Serialization.deserialize_object (typeof (Fruit), doc);
 
                                        // we expect 9 because Fruit triples it in the setter
                                        if (fruit.age != 9) {
-                                               Test.message ("Expected fruit.age [%d] but found [%d]", 9, 
fruit.age);
+                                               GLib.message ("Expected fruit.age [%d] but found [%d]", 9, 
fruit.age);
                                                assert_not_reached (); // TODO: check weight?
                                        }
                                } catch (GLib.Error e) {
-                                       Test.message ("%s", e.message);
+                                       GLib.message ("%s", e.message);
                                        assert_not_reached ();
                                }
                        });
@@ -353,7 +356,7 @@ class SerializationTest : GXmlTest {
                                /* Right now we can infer the type from a property's name, but fields we 
might need to specify */
                                try {
                                        doc = new Document.from_string ("<Object otype='Fruit'><Property 
pname='age'>3</Property></Object>");
-                                       fruit = (Fruit)Serialization.deserialize_object (doc);
+                                       fruit = (Fruit)Serialization.deserialize_object (typeof (Fruit), doc);
                                } catch (GLib.Error e) {
                                        Test.message ("%s", e.message);
                                        assert_not_reached ();
@@ -364,7 +367,7 @@ class SerializationTest : GXmlTest {
 
                                try {
                                        doc = new Document.from_string ("<Object otype='Fruit'><Property 
name='badname'>3</Property></Object>");
-                                       Serialization.deserialize_object (doc);
+                                       Serialization.deserialize_object (typeof (Fruit), doc);
                                        Test.message ("Expected SerializationError.UNKNOWN_PROPERTY to be 
thrown for property 'badname' in object 'Fruit' :(  Did not happen.");
                                        assert_not_reached ();
                                } catch (GXml.SerializationError.UNKNOWN_PROPERTY e) {
@@ -379,16 +382,19 @@ class SerializationTest : GXmlTest {
 
                                try {
                                        doc = new Document.from_string ("<Object otype='BadType'></Object>");
-                                       Serialization.deserialize_object (doc);
+                                       Serialization.deserialize_object (0, doc);
                                        assert_not_reached ();
-                               } catch (GXml.SerializationError.UNKNOWN_TYPE e) {
-                                       // Pass
                                } catch (GLib.Error e) {
-                                       Test.message ("%s", e.message);
-                                       assert_not_reached ();
+                                       if (e is SerializationError.UNKNOWN_TYPE) {
+                                       // pass
+                                       }
+                                       else {
+                                               Test.message ("%s", e.message);
+                                               assert_not_reached ();
+                                       }
                                }
                        });
-               Test.add_func ("/gxml/serialization/xml_deserialize_bad_property_type", () => {
+               Test.add_func ("/gxml/serialization/xml_deserialize_unknown_property_type", () => {
                                Document doc;
                                Fruit fruit;
 
@@ -396,14 +402,17 @@ class SerializationTest : GXmlTest {
                                Serialization.clear_cache ();
 
                                try {
-                                       doc = new Document.from_string ("<Object otype='Fruit'><Property 
pname='age' ptype='badtype'>blue</Property></Object>");
-                                       fruit = (Fruit)Serialization.deserialize_object (doc);
+                                       doc = new Document.from_string ("<Object otype='Fruit'><Property 
pname='unknown' ptype='badtype'>blue</Property></Object>");
+                                       fruit = (Fruit)Serialization.deserialize_object (typeof (Fruit), doc);
                                        assert_not_reached ();
-                               } catch (GXml.SerializationError.UNSUPPORTED_TYPE e) {
-                                       // Pass
                                } catch (GLib.Error e) {
-                                       Test.message ("%s", e.message);
-                                       assert_not_reached ();
+                                       if (e is SerializationError.UNKNOWN_PROPERTY)
+                                       { // pass
+                                       }
+                                       else {
+                                               Test.message ("%s", e.message);
+                                               assert_not_reached ();
+                                       }
                                }
                        });
                Test.add_func ("/gxml/serialization/simple_properties", () => {
@@ -438,7 +447,7 @@ class SerializationTest : GXmlTest {
                                        obj = new ComplexDuplicateProperties (simple_properties);
                                        xml = Serialization.serialize_object (obj);
 
-                                       restored = 
(ComplexDuplicateProperties)Serialization.deserialize_object (xml);
+                                       restored = 
(ComplexDuplicateProperties)Serialization.deserialize_object (typeof (ComplexDuplicateProperties), xml);
                                } catch (Error e) {
                                        Test.message ("%s", e.message);
                                        assert_not_reached ();
@@ -597,7 +606,7 @@ class SerializationTest : GXmlTest {
 
                                        try {
                                                doc = new Document.from_string ("<Object 
otype='Fruit'><Property pname='colour' ptype='gchararray'>blue</Property><Property pname='weight' 
ptype='gint'>11</Property><Property pname='name' ptype='gchararray'>fish</Property><Property pname='age' 
ptype='gint'>3</Property></Object>");
-                                               fruit = (Fruit)Serialization.deserialize_object (doc);
+                                               fruit = (Fruit)Serialization.deserialize_object (typeof 
(Fruit), doc);
 
                                                if (! fruit.test ("blue", 11, "fish", 3)) {
                                                        Test.message ("Expected [\"%s\", %d, \"%s\", %d] but 
found [%s]", "blue", 11, "fish", 3, fruit.to_string ());


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