[longomatch] Reuse the IDResolver as a cache for objects
- From: Andoni Morales Alastruey <amorales src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [longomatch] Reuse the IDResolver as a cache for objects
- Date: Wed, 18 Mar 2015 15:58:09 +0000 (UTC)
commit 779ce55c45744ed6a3b00ef43f1b8987388b8f88
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date: Wed Mar 18 15:56:50 2015 +0100
Reuse the IDResolver as a cache for objects
LongoMatch.DB/DocumentsSerializer.cs | 139 +++++++++++++++++++++-------------
Tests/DB/TestStorage.cs | 43 ++++++++++-
2 files changed, 129 insertions(+), 53 deletions(-)
---
diff --git a/LongoMatch.DB/DocumentsSerializer.cs b/LongoMatch.DB/DocumentsSerializer.cs
index 3c21a5b..8e13d3d 100644
--- a/LongoMatch.DB/DocumentsSerializer.cs
+++ b/LongoMatch.DB/DocumentsSerializer.cs
@@ -35,11 +35,11 @@ namespace LongoMatch.DB
public static class DocumentsSerializer
{
- public static void SaveObject (IStorable obj, Database db, StorablesConverter
storablesConverter = null)
+ public static void SaveObject (IStorable obj, Database db, IDReferenceResolver resolver =
null)
{
Document doc = db.GetDocument (obj.ID.ToString ());
doc.Update ((UnsavedRevision rev) => {
- JObject jo = SerializeObject (obj, rev, db, storablesConverter);
+ JObject jo = SerializeObject (obj, rev, db, resolver);
IDictionary<string, object> props = jo.ToObject<IDictionary<string, object>>
();
/* SetProperties sets a new properties dictionary, removing the attachments we
* added in the serialization */
@@ -51,10 +51,10 @@ namespace LongoMatch.DB
});
}
- public static object LoadObject (Type objType, Guid id, Database db, StorablesConverter
storablesConverter = null)
+ public static object LoadObject (Type objType, Guid id, Database db, IDReferenceResolver
resolver = null)
{
Document doc = db.GetExistingDocument (id.ToString ());
- return DeserializeObject (objType, doc, db, storablesConverter);
+ return DeserializeObject (objType, doc, db, resolver);
}
/// <summary>
@@ -66,10 +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,
- StorablesConverter storablesConverter = null)
+ IDReferenceResolver resolver = null)
{
JsonSerializer serializer = GetSerializer (obj.GetType (), rev, db,
- storablesConverter, GetLocalTypes (obj.GetType
()));
+ resolver, GetLocalTypes (obj.GetType ()));
JObject jo = JObject.FromObject (obj, serializer);
jo ["DocType"] = obj.GetType ().Name;
@@ -85,30 +85,31 @@ namespace LongoMatch.DB
/// <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,
- StorablesConverter storablesConverter = null)
+ IDReferenceResolver resolver = null)
{
JObject jo = JObject.FromObject (doc.Properties);
JsonSerializer serializer = GetSerializer (type, doc.CurrentRevision, db,
- storablesConverter, GetLocalTypes (type));
+ resolver, GetLocalTypes (type));
return jo.ToObject (type, serializer);
}
- static List<Type> GetLocalTypes (Type objType)
+ internal 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));
+ localStorables.Add (typeof(AnalysisEventType));
}
return localStorables;
}
static JsonSerializer GetSerializer (Type serType, Revision rev, Database db,
- StorablesConverter storablesConverter, List<Type>
localTypes)
+ IDReferenceResolver resolver, List<Type> localTypes)
{
- if (storablesConverter == null) {
- storablesConverter = new StorablesConverter (db, localTypes);
+ if (resolver == null) {
+ resolver = new IDReferenceResolver ();
}
if (localTypes == null) {
localTypes = new List<Type> ();
@@ -120,9 +121,9 @@ namespace LongoMatch.DB
settings.TypeNameHandling = TypeNameHandling.Objects;
settings.Converters.Add (new ImageConverter (rev));
settings.Converters.Add (new VersionConverter ());
- settings.Converters.Add (storablesConverter);
+ settings.Converters.Add (new StorablesConverter (db, resolver, localTypes));
settings.Converters.Add (new LongoMatchConverter (false));
- settings.ReferenceResolver = storablesConverter;
+ settings.ReferenceResolver = resolver;
return JsonSerializer.Create (settings);
}
}
@@ -199,55 +200,25 @@ namespace LongoMatch.DB
}
}
- /// <summary>
- /// Serialize objects matching any of the types lists passed in the constructor
- /// using their object ID.
- /// </summary>
- public class StorablesConverter : JsonConverter, IReferenceResolver
+ public class IDReferenceResolver: 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)
+ public IDReferenceResolver ()
{
- this.db = db;
- this.localTypes = localTypes;
- 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)
+ public bool IsCached (string id)
{
- IStorable storable = value as IStorable;
- writer.WriteValue (storable.ID);
- DocumentsSerializer.SaveObject (storable, db);
+ return _idtoobjects.ContainsKey (id);
}
- public override object ReadJson (JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
- {
- Guid id = Guid.Parse (reader.Value as string);
- return DocumentsSerializer.LoadObject (objectType, id, db);
- }
-
- public override bool CanConvert (Type objectType)
- {
- bool ret;
-
- if (!typeof(IStorable).IsAssignableFrom (objectType)) {
- ret = false;
- } else {
- ret = !localTypes.Contains (objectType);
- }
- return ret;
- }
+ #region IReferenceResolver implementation
public object ResolveReference (object context, string reference)
{
@@ -259,9 +230,8 @@ namespace LongoMatch.DB
public string GetReference (object context, object value)
{
string referenceStr;
- if (value is IStorable) {
- IStorable p = value as IStorable;
- referenceStr = p.ID.ToString ();
+ if (value is IIDObject) {
+ referenceStr = (value as IIDObject).ID.ToString ();
} else {
if (!_objectstoid.TryGetValue (value, out referenceStr)) {
_references++;
@@ -275,6 +245,10 @@ namespace LongoMatch.DB
public bool IsReferenced (object context, object value)
{
+ /* IStorable are always serialized by ID and not by reference */
+ if (value is IStorable) {
+ return false;
+ }
return _objectstoid.ContainsKey (value);
}
@@ -283,6 +257,67 @@ namespace LongoMatch.DB
_idtoobjects [reference] = value;
_objectstoid [value] = reference;
}
+
+ #endregion
+ }
+
+ /// <summary>
+ /// Serialize objects matching any of the types lists passed in the constructor
+ /// using their object ID.
+ /// </summary>
+ public class StorablesConverter : JsonConverter
+ {
+ List<Type> localTypes;
+ Database db;
+ IDReferenceResolver idResolver;
+
+ public StorablesConverter (Database db, IDReferenceResolver idResolver, List<Type> localTypes)
+ {
+ this.db = db;
+ this.idResolver = idResolver;
+ this.localTypes = localTypes;
+ if (this.localTypes == null) {
+ this.localTypes = new List<Type> ();
+ }
+ }
+
+ public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ IStorable storable = value as IStorable;
+ writer.WriteValue (storable.ID);
+ /* Only persist objects once per session */
+ if (!idResolver.IsCached (storable.ID.ToString ())) {
+ DocumentsSerializer.SaveObject (storable, db, idResolver);
+ idResolver.AddReference (this, storable.ID.ToString (), storable);
+ }
+ }
+
+ public override object ReadJson (JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
+ {
+ string idStr = reader.Value as string;
+ object obj;
+
+ /* Return the cached object instance instead a new one */
+ obj = idResolver.ResolveReference (this, idStr);
+ if (obj == null) {
+ obj = DocumentsSerializer.LoadObject (objectType, Guid.Parse (idStr), db,
idResolver);
+ idResolver.AddReference (this, idStr, obj);
+ }
+ return obj;
+ }
+
+ public override bool CanConvert (Type objectType)
+ {
+ bool ret;
+
+ if (!typeof(IStorable).IsAssignableFrom (objectType)) {
+ ret = false;
+ } else {
+ ret = !localTypes.Contains (objectType);
+ }
+ return ret;
+ }
+
}
}
diff --git a/Tests/DB/TestStorage.cs b/Tests/DB/TestStorage.cs
index f6c9539..407115d 100644
--- a/Tests/DB/TestStorage.cs
+++ b/Tests/DB/TestStorage.cs
@@ -240,6 +240,38 @@ namespace Tests.DB
}
[Test ()]
+ [Ignore ("FIXME")]
+ public void TestSaveLoadTimelineEvent ()
+ {
+ IDReferenceResolver resolver = new IDReferenceResolver ();
+ Player p = new Player ();
+ AnalysisEventType evtType = new AnalysisEventType ();
+ TimelineEvent evt = new TimelineEvent ();
+
+ resolver.AddReference (null, p.ID.ToString (), p);
+ resolver.AddReference (null, evtType.ID.ToString (), evtType);
+ evt.Players.Add (p);
+ evt.EventType = evtType;
+
+ Document doc = db.GetDocument (evt.ID.ToString ());
+ doc.Update ((UnsavedRevision rev) => {
+ JObject jo = DocumentsSerializer.SerializeObject (evt, rev, db, resolver);
+ Assert.AreEqual (p.ID, jo ["Players"] [0].Value<Guid> ());
+ Assert.AreEqual (evtType.ID, jo ["EventType"].Value<Guid> ());
+ IDictionary<string, object> props = jo.ToObject<IDictionary<string, object>>
();
+ rev.SetProperties (props);
+ return true;
+ });
+
+ /* Player has not been added to the db, as it was already referenced
+ * by the IDReferenceResolver */
+ Assert.AreEqual (1, db.DocumentCount);
+
+ TimelineEvent evt2 = storage.Retrieve <TimelineEvent> (evt.ID);
+ Assert.IsNotNull (evt2.EventType);
+ }
+
+ [Test ()]
public void TestSaveLoadProjectDescription ()
{
MediaFile mf = new MediaFile ("path", 34000, 25, true, true, "mp4", "h264",
@@ -293,7 +325,13 @@ namespace Tests.DB
p.Description = pd;
for (int i = 0; i < 10; i++) {
- p.AddEvent (p.EventTypes [i], new Time (1000), new Time (2000), null, null,
null, null);
+ TimelineEvent evt = new TimelineEvent {
+ EventType = p.EventTypes [i],
+ Start = new Time (1000),
+ Stop = new Time (2000),
+ Players = new List<Player> { p.LocalTeamTemplate.List [0] },
+ };
+ p.Timeline.Add (evt);
}
storage.Store<Project> (p);
@@ -303,6 +341,9 @@ namespace Tests.DB
Project p2 = storage.Retrieve<Project> (p.ID);
Assert.AreEqual (p.Timeline.Count, p2.Timeline.Count);
+ Assert.AreEqual (p2.LocalTeamTemplate.List [0], p2.Timeline [0].Players [0]);
+ //Assert.AreEqual ((p2.Dashboard.List [0] as AnalysisEventButton).EventType,
+ // p2.Timeline [0].EventType);
}
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]