[geary/wip/714217-offline] Finishing up on persistance/ module
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/714217-offline] Finishing up on persistance/ module
- Date: Fri, 13 Dec 2013 03:12:25 +0000 (UTC)
commit 4c4d37c1ffb715e1312dc553ebaa19bb290dcc57
Author: Jim Nelson <jim yorba org>
Date: Thu Dec 12 19:12:14 2013 -0800
Finishing up on persistance/ module
src/CMakeLists.txt | 1 +
.../persistance-data-flavor-serializer.vala | 20 +++---
.../persistance/persistance-data-flavor.vala | 3 +
.../persistance/persistance-deserializer.vala | 40 +++++++---
src/engine/persistance/persistance-error.vala | 12 +++
.../persistance/persistance-flavor-keyfile.vala | 61 ++++++++++-----
.../persistance/persistance-serializable.vala | 27 ++++++-
.../persistance/persistance-serialized-type.vala | 81 ++++++++++++++++++-
src/engine/persistance/persistance-serializer.vala | 10 ++-
src/engine/persistance/persistance.vala | 4 +-
10 files changed, 205 insertions(+), 54 deletions(-)
---
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9dcaf88..8385f02 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -245,6 +245,7 @@ engine/persistance/persistance-data-flavor.vala
engine/persistance/persistance-data-flavor-deserializer.vala
engine/persistance/persistance-data-flavor-serializer.vala
engine/persistance/persistance-deserializer.vala
+engine/persistance/persistance-error.vala
engine/persistance/persistance-flavor-keyfile.vala
engine/persistance/persistance-serializable.vala
engine/persistance/persistance-serialized-type.vala
diff --git a/src/engine/persistance/persistance-data-flavor-serializer.vala
b/src/engine/persistance/persistance-data-flavor-serializer.vala
index 641bfc1..38f9fa8 100644
--- a/src/engine/persistance/persistance-data-flavor-serializer.vala
+++ b/src/engine/persistance/persistance-data-flavor-serializer.vala
@@ -13,27 +13,27 @@
*/
public interface Geary.Persistance.DataFlavorSerializer : BaseObject {
- public abstract void set_bool(string name, bool b);
+ public abstract void set_bool(string name, bool b) throws Error;
- public abstract void set_int(string name, int i);
+ public abstract void set_int(string name, int i) throws Error;
- public abstract void set_int64(string name, int64 i64);
+ public abstract void set_int64(string name, int64 i64) throws Error;
- public abstract void set_float(string name, float f);
+ public abstract void set_float(string name, float f) throws Error;
- public abstract void set_double(string name, double d);
+ public abstract void set_double(string name, double d) throws Error;
- public abstract void set_utf8(string name, string utf8);
+ public abstract void set_utf8(string name, string utf8) throws Error;
- public abstract void set_int_array(string name, int[] iar);
+ public abstract void set_int_array(string name, int[] iar) throws Error;
- public abstract void set_utf8_array(string name, string[] utf8ar);
+ public abstract void set_utf8_array(string name, string[] utf8ar) throws Error;
/**
* Returns the serialized byte stream as a { link Geary.Memory.Buffer}.
*
- * The DataFlavorSerializer is not required to reset its state after this call. It should
- * expect to be discarded soon after commit() is invoked.
+ * The { link DataFlavorSerializer} is not required to reset its state after this call. It
+ * should expect to be discarded soon after commit() is invoked.
*/
internal abstract Geary.Memory.Buffer commit() throws Error;
}
diff --git a/src/engine/persistance/persistance-data-flavor.vala
b/src/engine/persistance/persistance-data-flavor.vala
index e3f52ba..7c18b4b 100644
--- a/src/engine/persistance/persistance-data-flavor.vala
+++ b/src/engine/persistance/persistance-data-flavor.vala
@@ -23,6 +23,9 @@ public interface Geary.Persistance.DataFlavor : BaseObject {
*/
internal abstract DataFlavorSerializer create_serializer(Serializable sobj);
+ /**
+ * Create a new { link DataFlavorDeserializer} to generate a { link Serializable} object.
+ */
internal abstract DataFlavorDeserializer create_deserializer(Geary.Memory.Buffer buffer) throws Error;
}
diff --git a/src/engine/persistance/persistance-deserializer.vala
b/src/engine/persistance/persistance-deserializer.vala
index c860e79..151b99f 100644
--- a/src/engine/persistance/persistance-deserializer.vala
+++ b/src/engine/persistance/persistance-deserializer.vala
@@ -33,20 +33,24 @@ public class Geary.Persistance.Deserializer : BaseObject {
public Serializable deserialize_properties(DataFlavorDeserializer deserializer)
throws Error {
- Serializable? sobj = activator.activate(deserializer.get_classname(),
- deserializer.get_serialized_version());
- // TODO: Need Errors
- assert(sobj != null);
+ string classname = deserializer.get_classname();
+ if (String.is_empty(classname))
+ throw new PersistanceError.ACTIVATION("Unable to activate record: no classname");
+
+ int version = deserializer.get_serialized_version();
+ Serializable? sobj = activator.activate(classname, version);
+ if (sobj == null)
+ throw new PersistanceError.ACTIVATION("Unable to activate %s:%d", classname, version);
foreach (ParamSpec param_spec in sobj.get_class().list_properties()) {
+ // quietly pass over unserializable properties ... up to Activator to fill them with
+ // values
if (!is_serializable(param_spec, false))
continue;
if (!deserializer.has_value(param_spec.name)) {
- debug("WARNING: Serialized stream does not contain parameter for %s",
- param_spec.name);
-
- continue;
+ throw new PersistanceError.NOT_FOUND("Property %s not stored for class %s:%d",
+ param_spec.name, classname, version);
}
// Give the object the chance to manually deserialize the property
@@ -70,11 +74,25 @@ public class Geary.Persistance.Deserializer : BaseObject {
value.set_int64(deserializer.get_int64(param_spec.name));
break;
+ case SerializedType.FLOAT:
+ value = Value(typeof(float));
+ value.set_float(deserializer.get_float(param_spec.name));
+ break;
+
+ case SerializedType.DOUBLE:
+ value = Value(typeof(double));
+ value.set_double(deserializer.get_double(param_spec.name));
+ break;
+
+ case SerializedType.UTF8:
+ value = Value(typeof(string));
+ value.set_string(deserializer.get_utf8(param_spec.name));
+ break;
+
case SerializedType.INT_ARRAY:
case SerializedType.UTF8_ARRAY:
- debug("WARNING: int[] and string[] properties must be manually deserialized");
-
- continue;
+ throw new PersistanceError.UNAVAILABLE("Property %s is an array, must be manually
deserialized (%s:%d)",
+ param_spec.name, classname, version);
default:
assert_not_reached();
diff --git a/src/engine/persistance/persistance-error.vala b/src/engine/persistance/persistance-error.vala
new file mode 100644
index 0000000..276b10b
--- /dev/null
+++ b/src/engine/persistance/persistance-error.vala
@@ -0,0 +1,12 @@
+/* Copyright 2013 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+public errordomain Geary.PersistanceError {
+ INVALID,
+ NOT_FOUND,
+ UNAVAILABLE,
+ ACTIVATION
+}
diff --git a/src/engine/persistance/persistance-flavor-keyfile.vala
b/src/engine/persistance/persistance-flavor-keyfile.vala
index bccc3a0..4b7c185 100644
--- a/src/engine/persistance/persistance-flavor-keyfile.vala
+++ b/src/engine/persistance/persistance-flavor-keyfile.vala
@@ -12,7 +12,7 @@
*/
public class Geary.Persistance.Flavor.GKeyFile : BaseObject, Geary.Persistance.DataFlavor {
- private const string VERSION_NAME = "__version__";
+ private const string VERSION_NAME = "__v__";
private class KeyFileSerializer : BaseObject, DataFlavorSerializer {
private string groupname;
@@ -21,47 +21,55 @@ public class Geary.Persistance.Flavor.GKeyFile : BaseObject, Geary.Persistance.D
public KeyFileSerializer(Serializable sobj) {
groupname = sobj.serialize_classname();
- // set the object version number
- keyfile.set_integer(groupname, VERSION_NAME, sobj.serialize_version());
+ // set the object interface version number
+ keyfile.set_integer(groupname, VERSION_NAME, sobj.interface_version());
}
- public void set_bool(string name, bool b) {
- keyfile.set_integer(groupname, typename(name), SerializedType.BOOL.serialize());
+ public void set_bool(string name, bool b) throws Error {
+ check_name(name);
+ keyfile.set_value(groupname, typename(name), SerializedType.BOOL.serialize());
keyfile.set_boolean(groupname, name, b);
}
- public void set_int(string name, int i) {
- keyfile.set_integer(groupname, typename(name), SerializedType.INT.serialize());
+ public void set_int(string name, int i) throws Error {
+ check_name(name);
+ keyfile.set_value(groupname, typename(name), SerializedType.INT.serialize());
keyfile.set_integer(groupname, name, i);
}
- public void set_int64(string name, int64 i64) {
- keyfile.set_integer(groupname, typename(name), SerializedType.INT64.serialize());
+ public void set_int64(string name, int64 i64) throws Error {
+ check_name(name);
+ keyfile.set_value(groupname, typename(name), SerializedType.INT64.serialize());
keyfile.set_int64(groupname, name, i64);
}
- public void set_float(string name, float f) {
- keyfile.set_integer(groupname, typename(name), SerializedType.FLOAT.serialize());
+ public void set_float(string name, float f) throws Error {
+ check_name(name);
+ keyfile.set_value(groupname, typename(name), SerializedType.FLOAT.serialize());
keyfile.set_double(groupname, name, f);
}
- public void set_double(string name, double d) {
- keyfile.set_integer(groupname, typename(name), SerializedType.DOUBLE.serialize());
+ public void set_double(string name, double d) throws Error {
+ check_name(name);
+ keyfile.set_value(groupname, typename(name), SerializedType.DOUBLE.serialize());
keyfile.set_double(groupname, name, d);
}
- public void set_utf8(string name, string utf8) {
- keyfile.set_integer(groupname, typename(name), SerializedType.UTF8.serialize());
+ public void set_utf8(string name, string utf8) throws Error {
+ check_name(name);
+ keyfile.set_value(groupname, typename(name), SerializedType.UTF8.serialize());
keyfile.set_string(groupname, name, utf8);
}
- public void set_int_array(string name, int[] iar) {
- keyfile.set_integer(groupname, typename(name), SerializedType.INT_ARRAY.serialize());
+ public void set_int_array(string name, int[] iar) throws Error {
+ check_name(name);
+ keyfile.set_value(groupname, typename(name), SerializedType.INT_ARRAY.serialize());
keyfile.set_integer_list(groupname, name, iar);
}
- public void set_utf8_array(string name, string[] utf8ar) {
- keyfile.set_integer(groupname, typename(name), SerializedType.UTF8_ARRAY.serialize());
+ public void set_utf8_array(string name, string[] utf8ar) throws Error {
+ check_name(name);
+ keyfile.set_value(groupname, typename(name), SerializedType.UTF8_ARRAY.serialize());
keyfile.set_string_list(groupname, name, utf8ar);
}
@@ -94,7 +102,7 @@ public class Geary.Persistance.Flavor.GKeyFile : BaseObject, Geary.Persistance.D
}
public SerializedType get_value_type(string name) throws Error {
- return SerializedType.deserialize(keyfile.get_integer(groupname, typename(name)));
+ return SerializedType.deserialize(keyfile.get_value(groupname, typename(name)));
}
public bool get_bool(string name) throws Error {
@@ -153,6 +161,19 @@ public class Geary.Persistance.Flavor.GKeyFile : BaseObject, Geary.Persistance.D
return "__t_%s__".printf(name);
}
+ /**
+ * TODO: Rather than spit invalid names back at the caller, transform them into something
+ * suitable and transform them back at deserialization time. For now, however, KeyFile doesn't
+ * support certain property names.
+ */
+ private static void check_name(string name) throws Error {
+ if (name.has_prefix("__")) {
+ throw new PersistanceError.INVALID(
+ "Data flavor KeyFile doesn't support property names with two leading underscores (%s)",
+ name);
+ }
+ }
+
internal DataFlavorSerializer create_serializer(Serializable sobj) {
return new KeyFileSerializer(sobj);
}
diff --git a/src/engine/persistance/persistance-serializable.vala
b/src/engine/persistance/persistance-serializable.vala
index b501b5d..c05a407 100644
--- a/src/engine/persistance/persistance-serializable.vala
+++ b/src/engine/persistance/persistance-serializable.vala
@@ -24,7 +24,7 @@ public interface Geary.Persistance.Serializable : Object {
*
* If the properties of the implementing class changes, this value should be incremented.
*/
- public abstract int serialize_version();
+ public abstract int interface_version();
/**
* Manual serialization of a property.
@@ -32,9 +32,30 @@ public interface Geary.Persistance.Serializable : Object {
* If { link Serializer} is incapable of serializing a property, this method is called.
* The object must either manually serialize the property (use name to determine which) and
* return true, or return false.
+ *
+ * In particular, although { link DataFlavorSerializer} offers methods to serialize integer
+ * and string arrays, Serializer is ''unable'' to automatically determine the type of those
+ * properties due to limitations of GType, and so the Serializable object must do those itself.
*/
- public abstract bool serialize_property(string name, DataFlavorSerializer serializer) throws Error;
+ public virtual bool serialize_property(string name, DataFlavorSerializer serializer) throws Error {
+ return false;
+ }
- public abstract bool deserialize_property(string name, DataFlavorDeserializer deserializer) throws Error;
+ /**
+ * Manual deserialization of a property.
+ *
+ * { link Deserializer} gives the { link Serializable} object a chance to manually deserialize
+ * a property before it attempts to do it automatically.
+ *
+ * If { link Serializer} is incapable of serializing a property, this method is called.
+ * The object must either manually serialize the property (use name to determine which) and
+ * return true, or return false. Integer and string arrays in particular must be deserialized
+ * manually.
+ *
+ * @see serialize_property
+ */
+ public virtual bool deserialize_property(string name, DataFlavorDeserializer deserializer) throws Error {
+ return false;
+ }
}
diff --git a/src/engine/persistance/persistance-serialized-type.vala
b/src/engine/persistance/persistance-serialized-type.vala
index 30df04c..8efd21e 100644
--- a/src/engine/persistance/persistance-serialized-type.vala
+++ b/src/engine/persistance/persistance-serialized-type.vala
@@ -10,7 +10,7 @@
* The integer values for this enumeration are immutable and will not change in the future.
*/
-public enum SerializedType {
+public enum Geary.Persistance.SerializedType {
BOOL = 0,
INT,
INT64,
@@ -20,12 +20,83 @@ public enum SerializedType {
INT_ARRAY,
UTF8_ARRAY;
- public int serialize() {
- return (int) this;
+ /**
+ * Returns a somewhat human-readable string for serializing a type.
+ *
+ * The enumerated values (0..n) won't change in the future, but if the { link DataFlavor}
+ * prefers to use a string rather than an integer value to store type information, this and
+ * { link deserialize} are available.
+ */
+ public unowned string serialize() throws Error {
+ if (!is_valid())
+ throw new PersistanceError.INVALID("Invalid SerializedType: %d", (int) this);
+
+ switch (this) {
+ case BOOL:
+ return "b";
+
+ case INT:
+ return "i";
+
+ case INT64:
+ return "i64";
+
+ case FLOAT:
+ return "f";
+
+ case DOUBLE:
+ return "d";
+
+ case UTF8:
+ return "s";
+
+ case INT_ARRAY:
+ return "iar";
+
+ case UTF8_ARRAY:
+ return "sar";
+
+ default:
+ assert_not_reached();
+ }
}
- public static SerializedType deserialize(int value) throws Error {
- return (SerializedType) value;
+ /**
+ * Deserializes a string from { link serialize} into a { link SerializedType}.
+ */
+ public static SerializedType deserialize(string value) throws Error {
+ switch (value) {
+ case "b":
+ return BOOL;
+
+ case "i":
+ return INT;
+
+ case "i64":
+ return INT64;
+
+ case "f":
+ return FLOAT;
+
+ case "d":
+ return DOUBLE;
+
+ case "s":
+ return UTF8;
+
+ case "iar":
+ return INT_ARRAY;
+
+ case "sar":
+ return UTF8_ARRAY;
+
+ default:
+ throw new PersistanceError.INVALID("Invalid SerializedType: %d", value);
+ }
+ }
+
+ public bool is_valid() {
+ return Numeric.int_in_range_inclusive(this, BOOL, UTF8_ARRAY);
}
}
diff --git a/src/engine/persistance/persistance-serializer.vala
b/src/engine/persistance/persistance-serializer.vala
index 7139c29..c85b9d3 100644
--- a/src/engine/persistance/persistance-serializer.vala
+++ b/src/engine/persistance/persistance-serializer.vala
@@ -21,6 +21,12 @@
public class Geary.Persistance.Serializer : BaseObject {
private DataFlavor flavor;
+ /**
+ * Fired during serialization when a property is encountered that { link Serializer} cannot
+ * serialize and the object itself does not manually serialize.
+ */
+ public signal void unsupported_property(Serializable sobj, string prop_name);
+
public Serializer(DataFlavor flavor) {
this.flavor = flavor;
}
@@ -60,11 +66,9 @@ public class Geary.Persistance.Serializer : BaseObject {
} else if (param_spec.value_type == typeof(string)) {
serializer.set_utf8(param_spec.name, (string) value);
} else if (!sobj.serialize_property(param_spec.name, serializer)) {
- debug("WARNING: %s type %s not supported by Serializer", param_spec.name,
- param_spec.value_type.name());
+ unsupported_property(sobj, param_spec.name);
}
}
}
}
-
diff --git a/src/engine/persistance/persistance.vala b/src/engine/persistance/persistance.vala
index 40f6f99..81141a2 100644
--- a/src/engine/persistance/persistance.vala
+++ b/src/engine/persistance/persistance.vala
@@ -19,14 +19,14 @@ namespace Geary.Persistance {
private bool is_serializable(ParamSpec param_spec, bool warn) {
if ((param_spec.flags & ParamFlags.READWRITE) == 0) {
if (warn) {
- debug("WARNING: %s type %s not read/write, cannot be serialized", param_spec.name,
+ debug("%s type %s not read/write, cannot be serialized", param_spec.name,
param_spec.value_type.name());
}
return false;
} else if ((param_spec.flags & ParamFlags.CONSTRUCT_ONLY) != 0) {
if (warn) {
- debug("WARNING: %s type %s is construct-only, cannot be serialized", param_spec.name,
+ debug("%s type %s is construct-only, cannot be serialized", param_spec.name,
param_spec.value_type.name());
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]