[longomatch] Add a IReferenceResolver as a cache for deserialized objects



commit 7a4352dcf0f8ec3cec97cf4bf4844721ca64a51b
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Tue Mar 17 15:33:02 2015 +0100

    Add a IReferenceResolver as a cache for deserialized objects

 LongoMatch.Core/Common/Serializer.cs |  179 +++++++++++++---------------------
 LongoMatch.DB/DocumentsSerializer.cs |  165 +++++++++++++++----------------
 2 files changed, 147 insertions(+), 197 deletions(-)
---
diff --git a/LongoMatch.Core/Common/Serializer.cs b/LongoMatch.Core/Common/Serializer.cs
index 93af38b..d2ef0d3 100644
--- a/LongoMatch.Core/Common/Serializer.cs
+++ b/LongoMatch.Core/Common/Serializer.cs
@@ -35,32 +35,33 @@ namespace LongoMatch.Core.Common
 {
        public class Serializer
        {
-               public static void Save<T>(T obj, Stream stream,
-                                          SerializationType type=SerializationType.Json) {
+               public static void Save<T> (T obj, Stream stream,
+                                           SerializationType type = SerializationType.Json)
+               {
                        switch (type) {
                        case SerializationType.Binary:
-                               BinaryFormatter formatter = new  BinaryFormatter();
-                               formatter.Serialize(stream, obj);
+                               BinaryFormatter formatter = new  BinaryFormatter ();
+                               formatter.Serialize (stream, obj);
                                break;
                        case SerializationType.Xml:
-                               XmlSerializer xmlformatter = new XmlSerializer(typeof(T));
-                               xmlformatter.Serialize(stream, obj);
+                               XmlSerializer xmlformatter = new XmlSerializer (typeof(T));
+                               xmlformatter.Serialize (stream, obj);
                                break;
                        case SerializationType.Json:
                                StreamWriter sw = new StreamWriter (stream, Encoding.UTF8);
                                sw.NewLine = "\n";
                                sw.Write (JsonConvert.SerializeObject (obj, JsonSettings));
-                               sw.Flush();
+                               sw.Flush ();
                                break;
                        }
                }
-               
+
                public static void Save<T> (T obj, string filepath,
-                                         SerializationType type=SerializationType.Json)
+                                           SerializationType type = SerializationType.Json)
                {
                        string tmpPath = filepath + ".tmp";
-                       using (Stream stream = new FileStream(tmpPath, FileMode.Create,
-                                                             FileAccess.Write, FileShare.None)) {
+                       using (Stream stream = new FileStream (tmpPath, FileMode.Create,
+                                                      FileAccess.Write, FileShare.None)) {
                                Save<T> (obj, stream, type);
                        }
                        if (File.Exists (filepath)) {
@@ -70,35 +71,38 @@ namespace LongoMatch.Core.Common
                        }
                }
 
-               public static T Load<T>(Stream stream,
-                                       SerializationType type=SerializationType.Json) {
+               public static T Load<T> (Stream stream,
+                                        SerializationType type = SerializationType.Json)
+               {
                        switch (type) {
                        case SerializationType.Binary:
-                               BinaryFormatter formatter = new BinaryFormatter();
-                               return (T)formatter.Deserialize(stream);
+                               BinaryFormatter formatter = new BinaryFormatter ();
+                               return (T)formatter.Deserialize (stream);
                        case SerializationType.Xml:
-                               XmlSerializer xmlformatter = new XmlSerializer(typeof(T));
-                               return (T) xmlformatter.Deserialize(stream);
+                               XmlSerializer xmlformatter = new XmlSerializer (typeof(T));
+                               return (T)xmlformatter.Deserialize (stream);
                        case SerializationType.Json:
                                StreamReader sr = new StreamReader (stream, Encoding.UTF8);
-                               return JsonConvert.DeserializeObject<T> (sr.ReadToEnd(), JsonSettings);
+                               return JsonConvert.DeserializeObject<T> (sr.ReadToEnd (), JsonSettings);
                        default:
-                               throw new Exception();
+                               throw new Exception ();
                        }
                }
-               
-               public static T Load<T>(string filepath,
-                                       SerializationType type=SerializationType.Json) {
-                       Stream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read, 
FileShare.Read);
+
+               public static T Load<T> (string filepath,
+                                        SerializationType type = SerializationType.Json)
+               {
+                       Stream stream = new FileStream (filepath, FileMode.Open, FileAccess.Read, 
FileShare.Read);
                        using (stream) {
                                return Load<T> (stream, type);
                        }
                }
-               
-               public static T LoadSafe<T>(string filepath) {
+
+               public static T LoadSafe<T> (string filepath)
+               {
                
                        Stream stream = new FileStream (filepath, FileMode.Open,
-                                                      FileAccess.Read, FileShare.Read);
+                                               FileAccess.Read, FileShare.Read);
                        using (stream) {
                                try {
                                        return Load<T> (stream, SerializationType.Json);
@@ -109,9 +113,9 @@ namespace LongoMatch.Core.Common
                                }
                        }
                }
-               
+
                static JsonSerializerSettings JsonSettings {
-                       get{
+                       get {
                                JsonSerializerSettings settings = new JsonSerializerSettings ();
                                settings.Formatting = Formatting.Indented;
                                settings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
@@ -123,133 +127,88 @@ namespace LongoMatch.Core.Common
                        }
                }
        }
-       
+
        public class LongoMatchConverter : JsonConverter
        {
                bool handleImages;
 
-               public LongoMatchConverter (bool handleImages) {
+               public LongoMatchConverter (bool handleImages)
+               {
                        this.handleImages = handleImages;
                }
 
-               public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+               public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
                {
                        if (value is Time) {
                                Time time = value as Time;
                                if (time != null) {
-                                       writer.WriteValue(time.MSeconds);
+                                       writer.WriteValue (time.MSeconds);
                                }
                        } else if (value is Color) {
                                Color color = value as Color;
                                if (color != null) {
-                                       writer.WriteValue(String.Format ("#{0}{1}{2}{3}",
-                                                                        color.R.ToString ("X2"),
-                                                                        color.G.ToString ("X2"),
-                                                                        color.B.ToString ("X2"),
-                                                                        color.A.ToString ("X2")));
+                                       writer.WriteValue (String.Format ("#{0}{1}{2}{3}",
+                                               color.R.ToString ("X2"),
+                                               color.G.ToString ("X2"),
+                                               color.B.ToString ("X2"),
+                                               color.A.ToString ("X2")));
                                }
                        } else if (value is Image) {
                                Image image = value as Image;
                                if (image != null) {
-                                       writer.WriteValue(image.Serialize());
+                                       writer.WriteValue (image.Serialize ());
                                }
                        } else if (value is HotKey) {
                                HotKey hotkey = value as HotKey;
                                if (hotkey != null) {
-                                       writer.WriteValue(String.Format ("{0} {1}", hotkey.Key, 
hotkey.Modifier));
+                                       writer.WriteValue (String.Format ("{0} {1}", hotkey.Key, 
hotkey.Modifier));
                                }
                        } else if (value is Point) {
                                Point p = value as Point;
                                if (p != null) {
-                                       writer.WriteValue(String.Format ("{0} {1}",
-                                                                        p.X.ToString 
(NumberFormatInfo.InvariantInfo),
-                                                                        p.Y.ToString 
(NumberFormatInfo.InvariantInfo)));
+                                       writer.WriteValue (String.Format ("{0} {1}",
+                                               p.X.ToString (NumberFormatInfo.InvariantInfo),
+                                               p.Y.ToString (NumberFormatInfo.InvariantInfo)));
                                }
                        }
                }
 
-               public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 
JsonSerializer serializer)
+               public override object ReadJson (JsonReader reader, Type objectType, object existingValue, 
JsonSerializer serializer)
                {
                        if (reader.Value != null) {
-                               if (objectType == typeof (Time)) {
-                                       Int64 t = (Int64) reader.Value;
-                                       return new Time((int)t);
-                               } else if (objectType == typeof (Color)) {
-                                       string rgbStr = (string) reader.Value;
+                               if (objectType == typeof(Time)) {
+                                       if (reader.ValueType == typeof(Int64)) {
+                                               return new Time ((int)(Int64)reader.Value);
+                                       } else {
+                                               return new Time ((Int32)reader.Value);
+                                       }
+                               } else if (objectType == typeof(Color)) {
+                                       string rgbStr = (string)reader.Value;
                                        return Color.Parse (rgbStr);
-                               } else if (objectType == typeof (Image)) {
+                               } else if (objectType == typeof(Image)) {
                                        byte[] buf = Convert.FromBase64String ((string)reader.Value); 
                                        return Image.Deserialize (buf);
-                               } else if (objectType == typeof (HotKey)) {
+                               } else if (objectType == typeof(HotKey)) {
                                        string[] hk = ((string)reader.Value).Split (' '); 
-                                       return new HotKey {Key = int.Parse(hk[0]), Modifier = 
int.Parse(hk[1])};
-                               } else if (objectType == typeof (Point)) {
+                                       return new HotKey { Key = int.Parse (hk [0]), Modifier = int.Parse 
(hk [1]) };
+                               } else if (objectType == typeof(Point)) {
                                        string[] ps = ((string)reader.Value).Split (' '); 
-                                       return new Point (double.Parse(ps[0], NumberFormatInfo.InvariantInfo),
-                                                         double.Parse(ps[1], 
NumberFormatInfo.InvariantInfo));
+                                       return new Point (double.Parse (ps [0], 
NumberFormatInfo.InvariantInfo),
+                                               double.Parse (ps [1], NumberFormatInfo.InvariantInfo));
                                }
                        }
                        return null;
                }
-               
-               public override bool CanConvert(Type objectType)
+
+               public override bool CanConvert (Type objectType)
                {
                        return (
-                               objectType == typeof(Time) ||
-                               objectType == typeof(Color) ||
-                               objectType == typeof(Point) ||
-                               objectType == typeof(HotKey) ||
-                               objectType == typeof(Image) && handleImages);
+                           objectType == typeof(Time) ||
+                           objectType == typeof(Color) ||
+                           objectType == typeof(Point) ||
+                           objectType == typeof(HotKey) ||
+                           objectType == typeof(Image) && handleImages);
                }
        }
-       
-    public class IdReferenceResolver : IReferenceResolver
-    {
-               private int _references;
-        private readonly Dictionary<string, object> _idtoobjects;
-        private readonly Dictionary<object, string> _objectstoid;
-
-               public IdReferenceResolver () {
-                       _references = 0;
-                       _idtoobjects = new Dictionary<string, object>();
-                       _objectstoid = new Dictionary<object, string>();
-               }
-               
-        public object ResolveReference(object context, string reference)
-        {
-                       object p;
-            _idtoobjects.TryGetValue(reference, out p);
-            return p;
-        }
-
-        public string GetReference(object context, object value)
-        {
-                       string referenceStr;
-                       if (value is IIDObject) {
-                               IIDObject p = (IIDObject)value;
-                               referenceStr = p.ID.ToString();
-                       } else {
-                               if (!_objectstoid.TryGetValue (value, out referenceStr)) {
-                                       _references++;
-                                       referenceStr = _references.ToString(CultureInfo.InvariantCulture); 
-                               }
-                       }
-                       _idtoobjects[referenceStr] = value;
-                       _objectstoid[value] = referenceStr;
-                       return referenceStr;
-        }
-
-        public bool IsReferenced(object context, object value)
-        {
-                       string reference;
-                       return _objectstoid.TryGetValue (value, out reference);
-        }
-
-        public void AddReference(object context, string reference, object value)
-        {
-                       _idtoobjects[reference] = value;
-                       _objectstoid[value] = reference;
-        }
-    }
 }
 
diff --git a/LongoMatch.DB/DocumentsSerializer.cs b/LongoMatch.DB/DocumentsSerializer.cs
index d89ccb8..3c21a5b 100644
--- a/LongoMatch.DB/DocumentsSerializer.cs
+++ b/LongoMatch.DB/DocumentsSerializer.cs
@@ -35,18 +35,11 @@ namespace LongoMatch.DB
        public static class DocumentsSerializer
        {
 
-               public static void SaveObject (IStorable obj, Database db, JsonSerializer serializer = null)
+               public static void SaveObject (IStorable obj, Database db, StorablesConverter 
storablesConverter = null)
                {
-                       List<Type> localStorables = new List<Type> ();
-                       if (obj is Project) {
-                               localStorables.Add (typeof(Team));
-                               localStorables.Add (typeof(Dashboard));
-                               localStorables.Add (typeof(Player));
-                       }
-
                        Document doc = db.GetDocument (obj.ID.ToString ());
                        doc.Update ((UnsavedRevision rev) => {
-                               JObject jo = SerializeObject (obj, rev, db, localStorables, serializer);
+                               JObject jo = SerializeObject (obj, rev, db, storablesConverter);
                                IDictionary<string, object> props = jo.ToObject<IDictionary<string, object>> 
();
                                /* SetProperties sets a new properties dictionary, removing the attachments we
                                         * added in the serialization */
@@ -58,10 +51,10 @@ namespace LongoMatch.DB
                        });
                }
 
-               public static object LoadObject (Type objType, Guid id, Database db, JsonSerializer 
serializer = null)
+               public static object LoadObject (Type objType, Guid id, Database db, StorablesConverter 
storablesConverter = null)
                {
                        Document doc = db.GetExistingDocument (id.ToString ());
-                       return DeserializeObject (objType, doc, db, serializer);
+                       return DeserializeObject (objType, doc, db, storablesConverter);
                }
 
                /// <summary>
@@ -73,11 +66,10 @@ namespace LongoMatch.DB
                /// <param name="localStorables">A list of <see cref="LongoMatch.Core.Interfaces.IStorable"/>
                /// types that should be serialized as local referencies instead of by document ID.</param>
                internal static JObject SerializeObject (IStorable obj, Revision rev, Database db,
-                                                        List<Type> localStorables, JsonSerializer serializer 
= null)
+                                                        StorablesConverter storablesConverter = null)
                {
-                       if (serializer == null) {
-                               serializer = GetSerializer (obj.GetType (), rev, db, localStorables);
-                       }
+                       JsonSerializer serializer = GetSerializer (obj.GetType (), rev, db,
+                                                           storablesConverter, GetLocalTypes (obj.GetType 
()));
 
                        JObject jo = JObject.FromObject (obj, serializer);
                        jo ["DocType"] = obj.GetType ().Name;
@@ -92,17 +84,32 @@ namespace LongoMatch.DB
                /// <param name="doc">The document to deserialize.</param>
                /// <param name = "serializer">The serializer to use when deserializing the object</param>
                /// <typeparam name="T">The 1st type parameter.</typeparam>
-               internal static object DeserializeObject (Type type, Document doc, Database db, 
JsonSerializer serializer = null)
+               internal static object DeserializeObject (Type type, Document doc, Database db,
+                                                         StorablesConverter storablesConverter = null)
                {
                        JObject jo = JObject.FromObject (doc.Properties);
-                       if (serializer == null) {
-                               serializer = GetSerializer (type, doc.CurrentRevision, db, null);
-                       }
+                       JsonSerializer serializer = GetSerializer (type, doc.CurrentRevision, db,
+                                                           storablesConverter, GetLocalTypes (type));
                        return jo.ToObject (type, serializer);
                }
 
-               static JsonSerializer GetSerializer (Type serType, Revision rev, Database db, List<Type> 
localTypes)
+               static List<Type> GetLocalTypes (Type objType)
                {
+                       List<Type> localStorables = new List<Type> ();
+                       if (objType == typeof(Project)) {
+                               localStorables.Add (typeof(Team));
+                               localStorables.Add (typeof(Dashboard));
+                               localStorables.Add (typeof(Player));
+                       }
+                       return localStorables;
+               }
+
+               static JsonSerializer GetSerializer (Type serType, Revision rev, Database db,
+                                                    StorablesConverter storablesConverter, List<Type> 
localTypes)
+               {
+                       if (storablesConverter == null) {
+                               storablesConverter = new StorablesConverter (db, localTypes);
+                       }
                        if (localTypes == null) {
                                localTypes = new List<Type> ();
                        }
@@ -113,76 +120,14 @@ namespace LongoMatch.DB
                        settings.TypeNameHandling = TypeNameHandling.Objects;
                        settings.Converters.Add (new ImageConverter (rev));
                        settings.Converters.Add (new VersionConverter ());
-                       settings.Converters.Add (new StorablesConverter (db, localTypes));
+                       settings.Converters.Add (storablesConverter);
                        settings.Converters.Add (new LongoMatchConverter (false));
-                       //settings.ReferenceResolver = new IDReferenceResolver (db);
+                       settings.ReferenceResolver = storablesConverter;
                        return JsonSerializer.Create (settings);
                }
        }
 
 
-       class IdReferenceResolver : IReferenceResolver
-       {
-               int _references;
-               readonly Dictionary<string, object> _idtoobjects;
-               readonly Dictionary<object, string> _objectstoid;
-               Database _db;
-               Type _parent;
-               Type[] _localRefType;
-
-               public IdReferenceResolver (Database db, Type parent, Type[] localRefTypes)
-               {
-                       _db = db;
-                       _parent = parent;
-                       _localRefType = localRefTypes;
-                       _references = 0;
-                       _idtoobjects = new Dictionary<string, object> ();
-                       _objectstoid = new Dictionary<object, string> ();
-               }
-
-               public object ResolveReference (object context, string reference)
-               {
-                       object p;
-                       _idtoobjects.TryGetValue (reference, out p);
-
-                       if (p == null) {
-                               //DocumentsSerializer.DeserializeObject ( Serializer.
-                       }
-                       return p;
-               }
-
-               public string GetReference (object context, object value)
-               {
-                       string referenceStr;
-                       if (value is IStorable) {
-                               IStorable p = value as IStorable;
-                               referenceStr = p.ID.ToString ();
-                       } else {
-                               if (!_objectstoid.TryGetValue (value, out referenceStr)) {
-                                       _references++;
-                                       referenceStr = _references.ToString (CultureInfo.InvariantCulture); 
-                               }
-                       }
-                       _idtoobjects [referenceStr] = value;
-                       _objectstoid [value] = referenceStr;
-                       return referenceStr;
-               }
-
-               public bool IsReferenced (object context, object value)
-               {
-                       if (value is IStorable) {
-                               return true;
-                       }
-                       return _objectstoid.ContainsKey (value);
-               }
-
-               public void AddReference (object context, string reference, object value)
-               {
-                       _idtoobjects [reference] = value;
-                       _objectstoid [value] = reference;
-               }
-       }
-
        /// <summary>
        /// Converts fields with <see cref="LongoMatch.Core.Common.Image"/> objects 
        /// into Attachments, using as field value the name of the attachment prefixed
@@ -258,10 +203,13 @@ namespace LongoMatch.DB
        /// Serialize objects matching any of the types lists passed in the constructor
        /// using their object ID.
        /// </summary>
-       class StorablesConverter : JsonConverter
+       public class StorablesConverter : JsonConverter, IReferenceResolver
        {
                List<Type> localTypes;
                Database db;
+               int _references;
+               readonly Dictionary<string, object> _idtoobjects;
+               readonly Dictionary<object, string> _objectstoid;
 
                public StorablesConverter (Database db, List<Type> localTypes)
                {
@@ -270,6 +218,10 @@ namespace LongoMatch.DB
                        if (this.localTypes == null) {
                                this.localTypes = new List<Type> ();
                        }
+
+                       _references = 0;
+                       _idtoobjects = new Dictionary<string, object> ();
+                       _objectstoid = new Dictionary<object, string> ();
                }
 
                public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
@@ -287,10 +239,49 @@ namespace LongoMatch.DB
 
                public override bool CanConvert (Type objectType)
                {
+                       bool ret;
+
                        if (!typeof(IStorable).IsAssignableFrom (objectType)) {
-                               return false;
+                               ret = false;
+                       } else {
+                               ret = !localTypes.Contains (objectType);
+                       }
+                       return ret;
+               }
+
+               public object ResolveReference (object context, string reference)
+               {
+                       object p;
+                       _idtoobjects.TryGetValue (reference, out p);
+                       return p;
+               }
+
+               public string GetReference (object context, object value)
+               {
+                       string referenceStr;
+                       if (value is IStorable) {
+                               IStorable p = value as IStorable;
+                               referenceStr = p.ID.ToString ();
+                       } else {
+                               if (!_objectstoid.TryGetValue (value, out referenceStr)) {
+                                       _references++;
+                                       referenceStr = _references.ToString (CultureInfo.InvariantCulture); 
+                               }
                        }
-                       return !localTypes.Contains (objectType);
+                       _idtoobjects [referenceStr] = value;
+                       _objectstoid [value] = referenceStr;
+                       return referenceStr;
+               }
+
+               public bool IsReferenced (object context, object value)
+               {
+                       return _objectstoid.ContainsKey (value);
+               }
+
+               public void AddReference (object context, string reference, object value)
+               {
+                       _idtoobjects [reference] = value;
+                       _objectstoid [value] = reference;
                }
        }
 }


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