[longomatch] Add support for storing documents referencing by ID



commit e779c82f0d0c761b4122a1a6992d69396c67b4c9
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Mon Mar 16 14:44:07 2015 +0100

    Add support for storing documents referencing by ID

 LongoMatch.Core/Interfaces/ITemplates.cs |   42 +++++++---
 LongoMatch.DB/CouchbaseStorage.cs        |   25 ++----
 LongoMatch.DB/DocumentsSerializer.cs     |  106 +++++++++++++++++++------
 Tests/DB/TestStorage.cs                  |  123 ++++++++++++++++++++++++------
 4 files changed, 218 insertions(+), 78 deletions(-)
---
diff --git a/LongoMatch.Core/Interfaces/ITemplates.cs b/LongoMatch.Core/Interfaces/ITemplates.cs
index 655eacc..64024e3 100644
--- a/LongoMatch.Core/Interfaces/ITemplates.cs
+++ b/LongoMatch.Core/Interfaces/ITemplates.cs
@@ -19,34 +19,52 @@ using System;
 using System.Collections.Generic;
 using LongoMatch.Core.Store;
 using LongoMatch.Core.Store.Templates;
-       
+
 namespace LongoMatch.Core.Interfaces
 {
        public interface ITemplate: IStorable
        {
-               string Name {get; set;}
+               string Name { get; set; }
        }
 
        public interface ITemplateProvider
        {
-               List<string> TemplatesNames {get;}
-               bool Exists(string name);
+               void CheckDefaultTemplate ();
+
+               List<string> TemplatesNames { get; }
+
+               bool Exists (string name);
+
                void Copy (string orig, string copy);
+
                void Delete (string templateName);
-               void Create (string templateName, params object [] list);
+
+               void Create (string templateName, params object[] list);
        }
-       
+
        public interface ITemplateProvider<T>: ITemplateProvider where T: ITemplate
        {
-               List<T> Templates {get;}
+               List<T> Templates { get; }
+
                T Load (string name);
+
                T LoadFile (string filename);
-               void Save (T template);
-               void Update (T template);
+
+               void Save (ITemplate template);
+
+               void Update (ITemplate template);
+
                void Register (T template);
        }
-       
-       public interface ICategoriesTemplatesProvider: ITemplateProvider<Dashboard> {}
-       public interface ITeamTemplatesProvider: ITemplateProvider<Team> {}
+
+       public interface ICategoriesTemplatesProvider: ITemplateProvider<Dashboard>
+       {
+
+       }
+
+       public interface ITeamTemplatesProvider: ITemplateProvider<Team>
+       {
+
+       }
 }
 
diff --git a/LongoMatch.DB/CouchbaseStorage.cs b/LongoMatch.DB/CouchbaseStorage.cs
index c0fe973..5949c49 100644
--- a/LongoMatch.DB/CouchbaseStorage.cs
+++ b/LongoMatch.DB/CouchbaseStorage.cs
@@ -31,7 +31,7 @@ namespace LongoMatch.DB
                public CouchbaseStorage (string databaseDir, string databaseName)
                {
                        Manager manager = new Manager (new System.IO.DirectoryInfo (databaseDir),
-                               ManagerOptions.Default);
+                                                 ManagerOptions.Default);
                        db = manager.GetDatabase (databaseName);
                }
 
@@ -40,6 +40,12 @@ namespace LongoMatch.DB
                                return db;
                        }
                }
+
+               public object Retrieve (Type type, Guid id)
+               {
+                       return DocumentsSerializer.LoadObject (type, id, db);
+               }
+
                #region IStorage implementation
 
                public List<T> RetrieveAll<T> () where T : IStorable
@@ -49,8 +55,7 @@ namespace LongoMatch.DB
 
                public T Retrieve<T> (Guid id) where T : IStorable
                {
-                       Document doc = db.GetExistingDocument (id.ToString());
-                       return DocumentsSerializer.DeserializeObject<T> (db, doc); 
+                       return (T)Retrieve (typeof(T), id);
                }
 
                public List<T> Retrieve<T> (Dictionary<string, object> filter) where T : IStorable
@@ -60,19 +65,7 @@ namespace LongoMatch.DB
 
                public void Store<T> (T t) where T : IStorable
                {
-                       Document doc = db.GetDocument (t.ID.ToString ());
-                       doc.Update((UnsavedRevision newRevision) => 
-                               {
-                                       JObject jo = DocumentsSerializer.SerializeObject (t, newRevision, 
null);
-                                       IDictionary<string, object> props = jo.ToObject<IDictionary<string, 
object>>();
-                                       /* SetProperties sets a new properties dictionary, removing the 
attachments we
-                                        * added in the serialization */
-                                       if (newRevision.Properties.ContainsKey ("_attachments")) {
-                                               props["_attachments"] = 
newRevision.Properties["_attachments"];
-                                       }
-                                       newRevision.SetProperties (props);
-                                       return true;
-                               });
+                       DocumentsSerializer.SaveObject (t, db);
                }
 
                public void Delete<T> (T t) where T : IStorable
diff --git a/LongoMatch.DB/DocumentsSerializer.cs b/LongoMatch.DB/DocumentsSerializer.cs
index 5f9769c..d89ccb8 100644
--- a/LongoMatch.DB/DocumentsSerializer.cs
+++ b/LongoMatch.DB/DocumentsSerializer.cs
@@ -27,11 +27,43 @@ using Newtonsoft.Json.Converters;
 using System.Globalization;
 using LongoMatch.Core.Common;
 using System.Reflection;
+using LongoMatch.Core.Store;
+using LongoMatch.Core.Store.Templates;
 
 namespace LongoMatch.DB
 {
        public static class DocumentsSerializer
        {
+
+               public static void SaveObject (IStorable obj, Database db, JsonSerializer serializer = 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);
+                               IDictionary<string, object> props = jo.ToObject<IDictionary<string, object>> 
();
+                               /* SetProperties sets a new properties dictionary, removing the attachments we
+                                        * added in the serialization */
+                               if (rev.Properties.ContainsKey ("_attachments")) {
+                                       props ["_attachments"] = rev.Properties ["_attachments"];
+                               }
+                               rev.SetProperties (props);
+                               return true;
+                       });
+               }
+
+               public static object LoadObject (Type objType, Guid id, Database db, JsonSerializer 
serializer = null)
+               {
+                       Document doc = db.GetExistingDocument (id.ToString ());
+                       return DeserializeObject (objType, doc, db, serializer);
+               }
+
                /// <summary>
                /// Serializes an object into a <c>JObject</c>.
                /// </summary>
@@ -40,11 +72,15 @@ namespace LongoMatch.DB
                /// <param name="rev">The document revision to serialize.</param>
                /// <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>
-               public static JObject SerializeObject (IStorable obj, Revision rev, List<Type> localStorables)
+               internal static JObject SerializeObject (IStorable obj, Revision rev, Database db,
+                                                        List<Type> localStorables, JsonSerializer serializer 
= null)
                {
-                       JObject jo = JObject.FromObject (obj,
-                               GetSerializer (obj.GetType (), null, rev, localStorables));
-                       jo["DocType"] = obj.GetType ().Name;
+                       if (serializer == null) {
+                               serializer = GetSerializer (obj.GetType (), rev, db, localStorables);
+                       }
+
+                       JObject jo = JObject.FromObject (obj, serializer);
+                       jo ["DocType"] = obj.GetType ().Name;
                        return jo;
                }
 
@@ -56,16 +92,16 @@ 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>
-               public static T DeserializeObject<T> (Database db, Document doc, JsonSerializer serializer = 
null)
+               internal static object DeserializeObject (Type type, Document doc, Database db, 
JsonSerializer serializer = null)
                {
                        JObject jo = JObject.FromObject (doc.Properties);
                        if (serializer == null) {
-                               serializer = GetSerializer (typeof(T), db, doc.CurrentRevision, null);
+                               serializer = GetSerializer (type, doc.CurrentRevision, db, null);
                        }
-                       return jo.ToObject<T> (serializer);
+                       return jo.ToObject (type, serializer);
                }
 
-               static JsonSerializer GetSerializer (Type serType, Database db, Revision rev, List<Type> 
localTypes)
+               static JsonSerializer GetSerializer (Type serType, Revision rev, Database db, List<Type> 
localTypes)
                {
                        if (localTypes == null) {
                                localTypes = new List<Type> ();
@@ -77,7 +113,7 @@ namespace LongoMatch.DB
                        settings.TypeNameHandling = TypeNameHandling.Objects;
                        settings.Converters.Add (new ImageConverter (rev));
                        settings.Converters.Add (new VersionConverter ());
-                       //settings.Converters.Add (new DocumentsIDConverter (localTypes));
+                       settings.Converters.Add (new StorablesConverter (db, localTypes));
                        settings.Converters.Add (new LongoMatchConverter (false));
                        //settings.ReferenceResolver = new IDReferenceResolver (db);
                        return JsonSerializer.Create (settings);
@@ -90,9 +126,15 @@ namespace LongoMatch.DB
                int _references;
                readonly Dictionary<string, object> _idtoobjects;
                readonly Dictionary<object, string> _objectstoid;
+               Database _db;
+               Type _parent;
+               Type[] _localRefType;
 
-               public IdReferenceResolver ()
+               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> ();
@@ -102,14 +144,18 @@ namespace LongoMatch.DB
                {
                        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 IIDObject) {
-                               IIDObject p = (IIDObject)value;
+                       if (value is IStorable) {
+                               IStorable p = value as IStorable;
                                referenceStr = p.ID.ToString ();
                        } else {
                                if (!_objectstoid.TryGetValue (value, out referenceStr)) {
@@ -124,8 +170,10 @@ namespace LongoMatch.DB
 
                public bool IsReferenced (object context, object value)
                {
-                       string reference;
-                       return _objectstoid.TryGetValue (value, out reference);
+                       if (value is IStorable) {
+                               return true;
+                       }
+                       return _objectstoid.ContainsKey (value);
                }
 
                public void AddReference (object context, string reference, object value)
@@ -154,7 +202,8 @@ namespace LongoMatch.DB
                        attachmentNamesCount = new Dictionary<string, int> ();
                }
 
-               string GetAttachmentName (JsonWriter writer) {
+               string GetAttachmentName (JsonWriter writer)
+               {
                        string propertyName;
                        if (writer.WriteState == WriteState.Array) {
                                propertyName = ((writer as JTokenWriter).Token.Last as JProperty).Name;
@@ -164,7 +213,7 @@ namespace LongoMatch.DB
                        if (!attachmentNamesCount.ContainsKey (propertyName)) {
                                attachmentNamesCount [propertyName] = 0;
                        }
-                       attachmentNamesCount [propertyName] ++;
+                       attachmentNamesCount [propertyName]++;
                        return string.Format ("{0}_{1}", propertyName, attachmentNamesCount [propertyName]);
                }
 
@@ -209,34 +258,39 @@ namespace LongoMatch.DB
        /// Serialize objects matching any of the types lists passed in the constructor
        /// using their object ID.
        /// </summary>
-       class DocumentsIDConverter : JsonConverter
+       class StorablesConverter : JsonConverter
        {
-               Type[] refTypes;
+               List<Type> localTypes;
+               Database db;
 
-               public DocumentsIDConverter (Type[] refTypes)
+               public StorablesConverter (Database db, List<Type> localTypes)
                {
-                       this.refTypes = refTypes;
-                       if (this.refTypes == null) {
-                               this.refTypes = new Type[0] { };
+                       this.db = db;
+                       this.localTypes = localTypes;
+                       if (this.localTypes == null) {
+                               this.localTypes = new List<Type> ();
                        }
                }
 
                public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
                {
-                       writer.WriteValue ((value as IIDObject).ID);
+                       IStorable storable = value as IStorable;
+                       writer.WriteValue (storable.ID);
+                       DocumentsSerializer.SaveObject (storable, db);
                }
 
                public override object ReadJson (JsonReader reader, Type objectType, object existingValue, 
JsonSerializer serializer)
                {
-                       throw new NotImplementedException ();
+                       Guid id = Guid.Parse (reader.Value as string);
+                       return DocumentsSerializer.LoadObject (objectType, id, db);
                }
 
                public override bool CanConvert (Type objectType)
                {
-                       if (refTypes == null) {
+                       if (!typeof(IStorable).IsAssignableFrom (objectType)) {
                                return false;
                        }
-                       return refTypes.Contains (objectType);
+                       return !localTypes.Contains (objectType);
                }
        }
 }
diff --git a/Tests/DB/TestStorage.cs b/Tests/DB/TestStorage.cs
index d0d3e17..f525567 100644
--- a/Tests/DB/TestStorage.cs
+++ b/Tests/DB/TestStorage.cs
@@ -29,13 +29,22 @@ using NUnit.Framework;
 
 namespace Tests.DB
 {
+       class StorableContainerTest: IStorable
+       {
+               public Guid ID { get; set; }
+
+               public StorableImageTest Image { get; set; }
+       }
 
-       class StorableImageTest : IStorable 
+       class StorableImageTest : IStorable
        {
                public Guid ID { get; set; }
+
                public Image Image1 { get; set; }
+
                public Image Image2 { get; set; }
-               public List<Image> Images { get; set;}
+
+               public List<Image> Images { get; set; }
        }
 
        [TestFixture ()]
@@ -45,19 +54,22 @@ namespace Tests.DB
                CouchbaseStorage storage;
 
                [TestFixtureSetUp]
-               public void InitDB () {
+               public void InitDB ()
+               {
                        string dbPath = Path.Combine (Path.GetTempPath (), "TestDB");
                        storage = new CouchbaseStorage (dbPath, "test-db");
                        db = storage.Database;
                }
 
                [TestFixtureTearDown]
-               public void DeleteDB () {
+               public void DeleteDB ()
+               {
                        Directory.Delete (db.Manager.Directory, true);
                }
 
                [TearDown]
-               public void CleanDB () {
+               public void CleanDB ()
+               {
                        foreach (var d in db.CreateAllDocumentsQuery ().Run()) {
                                db.GetDocument (d.DocumentId).Delete ();
                        }
@@ -70,22 +82,23 @@ namespace Tests.DB
                                ID = Guid.NewGuid (),
                        };
                        Document doc = db.CreateDocument ();
-                       JObject jo = DocumentsSerializer.SerializeObject (t, doc.CreateRevision (), null);
+                       JObject jo = DocumentsSerializer.SerializeObject (t, doc.CreateRevision (), db, null);
                        Assert.AreEqual (t.ID, jo.Value<Guid> ("ID"));
                        Assert.AreEqual ("StorableImageTest", jo.Value<string> ("DocType"));
                }
 
-               [Test()]
-               public void TestSerializeImages () {
+               [Test ()]
+               public void TestSerializeImages ()
+               {
                        Image img = Utils.LoadImageFromFile ();
                        StorableImageTest t = new StorableImageTest {
                                Image1 = img,
                                Image2 = img,
-                               ID = Guid.NewGuid(),
+                               ID = Guid.NewGuid (),
                        };
                        Document doc = db.CreateDocument ();
                        UnsavedRevision rev = doc.CreateRevision ();
-                       JObject jo = DocumentsSerializer.SerializeObject (t, rev, null);
+                       JObject jo = DocumentsSerializer.SerializeObject (t, rev, db, null);
                        Assert.IsNotNull (jo ["ID"]);
                        Assert.AreEqual ("attachment::Image1_1", jo ["Image1"].Value<string> ());
                        Assert.AreEqual ("attachment::Image2_1", jo ["Image2"].Value<string> ());
@@ -96,34 +109,36 @@ namespace Tests.DB
                        }
                }
 
-               [Test()]
-               public void TestSerializeImagesList () {
+               [Test ()]
+               public void TestSerializeImagesList ()
+               {
                        Image img = Utils.LoadImageFromFile ();
                        StorableImageTest t = new StorableImageTest {
-                               Images = new List<Image> {img, img, img},
-                               ID = Guid.NewGuid(),
+                               Images = new List<Image> { img, img, img },
+                               ID = Guid.NewGuid (),
                        };
                        Document doc = db.CreateDocument ();
                        UnsavedRevision rev = doc.CreateRevision ();
-                       JObject jo = DocumentsSerializer.SerializeObject (t, rev, null);
+                       JObject jo = DocumentsSerializer.SerializeObject (t, rev, db, null);
                        int i = 0;
                        foreach (string name in rev.AttachmentNames) {
                                i++;
                                Assert.AreEqual ("Images_" + i, name);
                        }
                        Assert.AreEqual (3, i);
-                       Assert.AreEqual ("attachment::Images_1", jo ["Images"][0].Value<string>());
-                       Assert.AreEqual ("attachment::Images_2", jo ["Images"][1].Value<string>());
-                       Assert.AreEqual ("attachment::Images_3", jo ["Images"][2].Value<string>());
+                       Assert.AreEqual ("attachment::Images_1", jo ["Images"] [0].Value<string> ());
+                       Assert.AreEqual ("attachment::Images_2", jo ["Images"] [1].Value<string> ());
+                       Assert.AreEqual ("attachment::Images_3", jo ["Images"] [2].Value<string> ());
                }
 
-               [Test()]
-               public void TestDeserializeImages () {
+               [Test ()]
+               public void TestDeserializeImages ()
+               {
                        Image img = Utils.LoadImageFromFile ();
                        StorableImageTest t = new StorableImageTest {
                                Image1 = img,
                                Image2 = img,
-                               ID = Guid.NewGuid(),
+                               ID = Guid.NewGuid (),
                        };
                        storage.Store (t);
                        var test2 = storage.Retrieve<StorableImageTest> (t.ID);
@@ -134,12 +149,50 @@ namespace Tests.DB
                }
 
                [Test ()]
+               public void TestSerializeStorableByReference ()
+               {
+                       StorableImageTest img = new StorableImageTest {
+                               ID = Guid.NewGuid (),
+                               Image1 = Utils.LoadImageFromFile (),
+                       };
+                       StorableContainerTest cont = new StorableContainerTest {
+                               ID = Guid.NewGuid (),
+                               Image = img,
+                       };
+                       Document doc = db.CreateDocument ();
+                       UnsavedRevision rev = doc.CreateRevision ();
+                       JObject jo = DocumentsSerializer.SerializeObject (cont, rev, db, null);
+                       Assert.AreEqual (img.ID, jo ["Image"].Value<Guid> ());
+                       Assert.AreEqual (1, db.DocumentCount);
+                       Assert.IsNotNull (storage.Retrieve<StorableImageTest> (img.ID));
+                       rev.Save ();
+                       Assert.AreEqual (2, db.DocumentCount);
+               }
+
+               [Test ()]
+               public void TestDeserializeStorableByReference ()
+               {
+                       StorableImageTest img = new StorableImageTest {
+                               ID = Guid.NewGuid (),
+                               Image1 = Utils.LoadImageFromFile (),
+                       };
+                       StorableContainerTest cont = new StorableContainerTest {
+                               ID = Guid.NewGuid (),
+                               Image = img,
+                       };
+                       storage.Store (cont);
+                       var cont2 = storage.Retrieve <StorableContainerTest> (cont.ID);
+                       Assert.IsNotNull (cont2.Image);
+                       Assert.AreEqual (img.ID, cont2.Image.ID);
+               }
+
+               [Test ()]
                public void TestSaveDashboard ()
                {
                        Dashboard dashboard = Dashboard.DefaultTemplate (10);
                        storage.Store (dashboard);
                        Assert.AreEqual (1, db.DocumentCount);
-                       Assert.IsNotNull (db.GetExistingDocument (dashboard.ID.ToString()));
+                       Assert.IsNotNull (db.GetExistingDocument (dashboard.ID.ToString ()));
                }
 
                [Test ()]
@@ -147,7 +200,7 @@ namespace Tests.DB
                {
                        Dashboard dashboard = Dashboard.DefaultTemplate (10);
                        dashboard.Image = dashboard.GoalBackground =
-                               dashboard.HalfFieldBackground = dashboard.FieldBackground = 
Utils.LoadImageFromFile();
+                               dashboard.HalfFieldBackground = dashboard.FieldBackground = 
Utils.LoadImageFromFile ();
                        storage.Store (dashboard);
                        Dashboard dashboard2 = storage.Retrieve<Dashboard> (dashboard.ID);
                        Assert.IsNotNull (dashboard2);
@@ -171,7 +224,7 @@ namespace Tests.DB
                        };
                        storage.Store (player);
                        Assert.AreEqual (1, db.DocumentCount);
-                       Assert.IsNotNull (db.GetExistingDocument (player.ID.ToString()));
+                       Assert.IsNotNull (db.GetExistingDocument (player.ID.ToString ()));
                }
 
                [Test ()]
@@ -189,6 +242,28 @@ namespace Tests.DB
                        Assert.AreEqual (player1.ToString (), player2.ToString ());
                        Assert.AreEqual (player1.Photo.Width, player2.Photo.Width);
                }
+
+               [Test ()]
+               public void TestSaveTeam ()
+               {
+                       Team team = Team.DefaultTemplate (10);
+                       storage.Store<Team> (team);
+                       Assert.AreEqual (11, db.DocumentCount);
+               }
+
+               [Test ()]
+               public void TestLoadTeam ()
+               {
+                       Team team = Team.DefaultTemplate (10);
+                       storage.Store<Team> (team);
+                       Team team2 = storage.Retrieve<Team> (team.ID);
+                       Assert.AreEqual (team.ID, team2.ID);
+                       Assert.AreEqual (team.List.Count, team2.List.Count);
+
+                       for (int i = 0; i < team.List.Count; i++) {
+                               Assert.AreEqual (team.List [i].ID, team2.List [i].ID);
+                       }
+               }
        }
 }
 


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