[longomatch] Add support for storing documents referencing by ID
- From: Andoni Morales Alastruey <amorales src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [longomatch] Add support for storing documents referencing by ID
- Date: Wed, 18 Mar 2015 14:47:10 +0000 (UTC)
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]