[longomatch] Start with Coubase Lite database implementation



commit e3aaa8eac0d91334cb4a12e932898ef47f61dbdb
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Fri Mar 13 10:55:05 2015 +0100

    Start with Coubase Lite database implementation

 LongoMatch.Core/LongoMatch.Core.csproj       |    1 +
 LongoMatch.Core/Store/Player.cs              |    2 +-
 LongoMatch.Core/Store/Templates/Dashboard.cs |    2 +-
 LongoMatch.DB/AssemblyInfo.cs                |   21 +++
 LongoMatch.DB/CouchbaseStorage.cs            |   91 ++++++++++
 LongoMatch.DB/Documents/DocumentHelpers.cs   |   47 +++++
 LongoMatch.DB/DocumentsSerializer.cs         |  248 ++++++++++++++++++++++++++
 LongoMatch.DB/LongoMatch.DB.csproj           |   54 ++++++
 LongoMatch.DB/Makefile.am                    |   15 ++
 LongoMatch.sln                               |    7 +-
 Makefile.am                                  |    1 +
 Tests/DB/TestStorage.cs                      |  160 +++++++++++++++++
 Tests/Makefile.am                            |    2 +
 Tests/Tests.csproj                           |   14 ++-
 build/build.environment.mk                   |    8 +
 configure.ac                                 |    5 +
 16 files changed, 673 insertions(+), 5 deletions(-)
---
diff --git a/LongoMatch.Core/LongoMatch.Core.csproj b/LongoMatch.Core/LongoMatch.Core.csproj
index 500993c..9055417 100644
--- a/LongoMatch.Core/LongoMatch.Core.csproj
+++ b/LongoMatch.Core/LongoMatch.Core.csproj
@@ -163,6 +163,7 @@
     <Reference Include="System.Drawing" />
     <Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=b9a188c8922137c6">
       <Package>newtonsoft-json</Package>
+      <SpecificVersion>False</SpecificVersion>
     </Reference>
     <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.Xml" />
diff --git a/LongoMatch.Core/Store/Player.cs b/LongoMatch.Core/Store/Player.cs
index 76e6255..56ed650 100644
--- a/LongoMatch.Core/Store/Player.cs
+++ b/LongoMatch.Core/Store/Player.cs
@@ -27,7 +27,7 @@ namespace LongoMatch.Core.Store
        /// Player of a team
        /// </summary>
        [Serializable]
-       public class Player: IIDObject
+       public class Player: IStorable
        {
 
                #region Constructors
diff --git a/LongoMatch.Core/Store/Templates/Dashboard.cs b/LongoMatch.Core/Store/Templates/Dashboard.cs
index 8677e44..6016585 100644
--- a/LongoMatch.Core/Store/Templates/Dashboard.cs
+++ b/LongoMatch.Core/Store/Templates/Dashboard.cs
@@ -42,7 +42,7 @@ namespace LongoMatch.Core.Store.Templates
        /// The <see cref="LongoMatch.DB.Project"/> must handle all the changes
        /// </summary>
        [Serializable]
-       public class Dashboard: ITemplate, IDeserializationCallback
+       public class Dashboard: IStorable, ITemplate, IDeserializationCallback
        {
 
                const int CAT_WIDTH = 120;
diff --git a/LongoMatch.DB/AssemblyInfo.cs b/LongoMatch.DB/AssemblyInfo.cs
new file mode 100644
index 0000000..781dc38
--- /dev/null
+++ b/LongoMatch.DB/AssemblyInfo.cs
@@ -0,0 +1,21 @@
+//
+//  Copyright (C) 2015 Andoni Morales Alastruey
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+using System;
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("Tests")]
diff --git a/LongoMatch.DB/CouchbaseStorage.cs b/LongoMatch.DB/CouchbaseStorage.cs
new file mode 100644
index 0000000..eaf9885
--- /dev/null
+++ b/LongoMatch.DB/CouchbaseStorage.cs
@@ -0,0 +1,91 @@
+//
+//  Copyright (C) 2015 Andoni Morales Alastruey
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Couchbase.Lite;
+using LongoMatch.Core.Interfaces;
+using Newtonsoft.Json.Linq;
+
+namespace LongoMatch.DB
+{
+       public class CouchbaseStorage: IStorage
+       {
+               Database db;
+
+               public CouchbaseStorage (string databaseDir, string databaseName)
+               {
+                       Manager manager = new Manager (new System.IO.DirectoryInfo (databaseDir),
+                               ManagerOptions.Default);
+                       db = manager.GetDatabase (databaseName);
+               }
+
+               internal Database Database {
+                       get {
+                               return db;
+                       }
+               }
+               #region IStorage implementation
+
+               public List<T> RetrieveAll<T> () where T : IStorable
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public T Retrieve<T> (Guid id) where T : IStorable
+               {
+                       Document doc = db.GetExistingDocument (id.ToString());
+                       return DocumentsSerializer.DeserializeObject<T> (db, doc); 
+               }
+
+               public List<T> Retrieve<T> (Dictionary<string, object> filter) where T : IStorable
+               {
+                       throw new NotImplementedException ();
+               }
+
+               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, 
true, 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;
+                               });
+               }
+
+               public void Delete<T> (T t) where T : IStorable
+               {
+                       db.GetDocument (t.ID.ToString ()).Delete ();
+               }
+
+               public void Reset ()
+               {
+                       db.Manager.ForgetDatabase (db);
+               }
+
+               #endregion
+       }
+}
+
diff --git a/LongoMatch.DB/Documents/DocumentHelpers.cs b/LongoMatch.DB/Documents/DocumentHelpers.cs
new file mode 100644
index 0000000..9495638
--- /dev/null
+++ b/LongoMatch.DB/Documents/DocumentHelpers.cs
@@ -0,0 +1,47 @@
+//
+//  Copyright (C) 2015 Andoni Morales Alastruey
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+using System;
+using System.Linq;
+using Couchbase.Lite;
+using LongoMatch.Core.Common;
+
+namespace LongoMatch.DB.Documents
+{
+       public static class DocumentHelpers
+       {
+
+               static public void AddImageAttachment (UnsavedRevision rev, string name, Image img) {
+                       if (img == null) {
+                               if (rev.AttachmentNames.Contains (name)) {
+                                       rev.RemoveAttachment (name);
+                               }
+                       } else {
+                               rev.SetAttachment (name, "image/png", img.Serialize());
+                       }
+               }
+
+               static public Image ImageFromAttachment (Document doc, string name) {
+                       if (!doc.CurrentRevision.AttachmentNames.Contains (name)) {
+                               return null;
+                       }
+                       Attachment att = doc.CurrentRevision.GetAttachment (name);
+                       return Image.Deserialize (att.Content.ToArray());
+               }
+       }
+}
+
diff --git a/LongoMatch.DB/DocumentsSerializer.cs b/LongoMatch.DB/DocumentsSerializer.cs
new file mode 100644
index 0000000..728e9bc
--- /dev/null
+++ b/LongoMatch.DB/DocumentsSerializer.cs
@@ -0,0 +1,248 @@
+//
+//  Copyright (C) 2015 Andoni Morales Alastruey
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+using System;
+using System.Linq;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Couchbase.Lite;
+using LongoMatch.Core.Interfaces;
+using System.Collections.Generic;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Converters;
+using System.Globalization;
+using LongoMatch.Core.Common;
+using System.Reflection;
+
+namespace LongoMatch.DB
+{
+       public static class DocumentsSerializer
+       {
+               /// <summary>
+               /// Serializes an object into a <c>JObject</c>.
+               /// </summary>
+               /// <returns>A new object serialized.</returns>
+               /// <param name="obj">The <c>IStorable</c> to serialize.</param>
+               /// <param name="preserveReferences">If set to <c>true</c> preserve references.</param>
+               /// <param name="refTypes">A list of types that should be serialized by ID.</param>
+               /// <param name="skipFields">Extra fields that shouldn't be serialized.</param>
+               public static JObject SerializeObject (IStorable obj, Revision rev, bool preserveReferences,
+                                                      Type[] refTypes)
+               {
+                       JObject jo = JObject.FromObject (obj,
+                               GetSerializer (null, rev, preserveReferences, refTypes));
+                       jo["DocType"] = obj.GetType ().Name;
+                       return jo;
+               }
+
+               /// <summary>
+               /// Deserializes a <c>Document</c>
+               /// </summary>
+               /// <returns>A new object deserialized.</returns>
+               /// <param name="db">The <c>Database</c> where the Document is stored.</param>
+               /// <param name="doc">The document to deserialize.</param>
+               /// <typeparam name="T">The 1st type parameter.</typeparam>
+               public static T DeserializeObject<T> (Database db, Document doc)
+               {
+                       JObject jo = JObject.FromObject (doc.Properties);
+                       return jo.ToObject<T> (GetSerializer (db, doc.CurrentRevision, true, null));
+               }
+
+               static JsonSerializer GetSerializer (Database db, Revision rev,
+                                                    bool preserveReferences, Type[] refTypes)
+               {
+                       JsonSerializerSettings settings = new JsonSerializerSettings ();
+                       settings.Formatting = Formatting.Indented;
+                       if (preserveReferences) {
+                               settings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
+                       }
+                       settings.TypeNameHandling = TypeNameHandling.Objects;
+                       settings.ContractResolver = new ImagePropertiesContractResolver (rev);
+                       settings.Converters.Add (new ImageConverter (rev));
+                       settings.Converters.Add (new VersionConverter ());
+                       settings.Converters.Add (new DocumentsIDConverter (refTypes));
+                       settings.Converters.Add (new LongoMatchConverter (false));
+                       //settings.ReferenceResolver = new IDReferenceResolver (db);
+                       return JsonSerializer.Create (settings);
+               }
+       }
+
+
+       /// <summary>
+       /// Prevents serializing properties with <c>Image</c> objects that should be stored
+       /// as attachments
+       /// </summary>
+       class ImagePropertiesContractResolver : DefaultContractResolver
+       {
+               ImageConverter imgConverter;
+
+               public ImagePropertiesContractResolver (Revision rev)
+               {
+                       imgConverter = new ImageConverter (rev);
+               }
+
+               protected override JsonProperty CreateProperty (MemberInfo member,
+                                                               MemberSerialization memberSerialization)
+               {
+                       JsonProperty property = base.CreateProperty (member, memberSerialization);
+
+                       if (property.PropertyType == typeof(Image)) {
+                               property.ShouldSerialize = d => true;
+                       }
+                       return property;
+               }
+       }
+
+       class IdReferenceResolver : IReferenceResolver
+       {
+               int _references;
+               readonly Dictionary<string, object> _idtoobjects;
+               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;
+               }
+       }
+
+       /// <summary>
+       /// Converts fields with <see cref="LongoMatch.Core.Common.Image"/> objects 
+       /// into Attachments, using as field value the name of the attachment prefixed
+       /// with the <c>attachment::</c> string.
+       /// In the desrialization process, it loads <see cref="LongoMatch.Core.Common.Image"/>
+       /// from the attachment with the same as the set in the property.
+       /// </summary>
+       class ImageConverter : JsonConverter
+       {
+               Revision rev;
+               const string ATTACHMENT = "attachment::";
+
+               public ImageConverter (Revision rev)
+               {
+                       this.rev = rev;
+               }
+
+               public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
+               {
+                       (rev as UnsavedRevision).SetAttachment (writer.Path, "image/png",
+                               (value as Image).Serialize ());
+                       writer.WriteValue (ATTACHMENT + writer.Path);
+               }
+
+               public override object ReadJson (JsonReader reader, Type objectType,
+                                                object existingValue, JsonSerializer serializer)
+               {
+                       if (objectType == typeof(Image)) {
+                               string valueString = reader.Value as string;
+
+                               if (valueString == null) {
+                                       return null;
+                               }
+                               if (valueString.StartsWith (ATTACHMENT)) {
+                                       string attachmentName = valueString.Replace (ATTACHMENT, "");
+                                       Attachment attachment = rev.GetAttachment (attachmentName);
+                                       if (attachment == null) {
+                                               return null;
+                                       }
+                                       return Image.Deserialize (attachment.Content.ToArray ());
+                               } else {
+                                       throw new InvalidCastException ();
+                               }
+                       }
+                       return reader.Value;
+               }
+
+               public override bool CanConvert (Type objectType)
+               {
+                       return objectType.Equals (typeof(Image));
+               }
+       }
+
+       /// <summary>
+       /// Serialize objects matching any of the types lists passed in the constructor
+       /// using their object ID.
+       /// </summary>
+       class DocumentsIDConverter : JsonConverter
+       {
+               Type[] refTypes;
+
+               public DocumentsIDConverter (Type[] refTypes)
+               {
+                       this.refTypes = refTypes;
+                       if (this.refTypes == null) {
+                               this.refTypes = new Type[0] { };
+                       }
+               }
+
+               public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
+               {
+                       writer.WriteValue ((value as IIDObject).ID);
+               }
+
+               public override object ReadJson (JsonReader reader, Type objectType, object existingValue, 
JsonSerializer serializer)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public override bool CanConvert (Type objectType)
+               {
+                       if (refTypes == null) {
+                               return false;
+                       }
+                       return refTypes.Contains (objectType);
+               }
+       }
+}
+
diff --git a/LongoMatch.DB/LongoMatch.DB.csproj b/LongoMatch.DB/LongoMatch.DB.csproj
new file mode 100644
index 0000000..85139db
--- /dev/null
+++ b/LongoMatch.DB/LongoMatch.DB.csproj
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" 
xmlns="http://schemas.microsoft.com/developer/msbuild/2003";>
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{EC395325-994F-47F6-8FC2-AC17EC452EDA}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>LongoMatch.DB</RootNamespace>
+    <AssemblyName>LongoMatch.DB</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>full</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=b9a188c8922137c6">
+      <Package>newtonsoft-json</Package>
+      <SpecificVersion>False</SpecificVersion>
+    </Reference>
+    <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+    <Reference Include="Couchbase.Lite, Version=1.0.4.275, Culture=neutral">
+      <Package>couchbase-lite</Package>
+      <SpecificVersion>False</SpecificVersion>
+    </Reference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <Compile Include="AssemblyInfo.cs" />
+    <Compile Include="CouchbaseStorage.cs" />
+    <Compile Include="DocumentsSerializer.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\LongoMatch.Core\LongoMatch.Core.csproj">
+      <Project>{B70912B2-7ED5-450E-97BD-45A3D45A0358}</Project>
+      <Name>LongoMatch.Core</Name>
+    </ProjectReference>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/LongoMatch.DB/Makefile.am b/LongoMatch.DB/Makefile.am
new file mode 100644
index 0000000..d9d809e
--- /dev/null
+++ b/LongoMatch.DB/Makefile.am
@@ -0,0 +1,15 @@
+ASSEMBLY = LongoMatch.DB
+TARGET = library
+
+LINK = $(REF_DEP_LONGOMATCH_DB)
+
+SOURCES = AssemblyInfo.cs \
+       Documents/DashboardDocument.cs \
+       Documents/DocumentHelpers.cs \
+       Documents/Serializer.cs
+
+RESOURCES = 
+
+EXTRA_BUNDLE = $(COUCHBASE_LIBS_PATHS)
+
+include $(top_srcdir)/build/build.mk
diff --git a/LongoMatch.sln b/LongoMatch.sln
index f92a30a..fb21187 100644
--- a/LongoMatch.sln
+++ b/LongoMatch.sln
@@ -35,6 +35,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LongoMatch.Plugins.Stats",
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", 
"{F042D024-3283-4E60-9A85-76E6BBBBB2C1}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LongoMatch.DB", "LongoMatch.DB\LongoMatch.DB.csproj", 
"{EC395325-994F-47F6-8FC2-AC17EC452EDA}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
@@ -101,6 +103,10 @@ Global
                {E75E30DC-C1CF-4683-9A36-65B91EF10095}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {E75E30DC-C1CF-4683-9A36-65B91EF10095}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {E75E30DC-C1CF-4683-9A36-65B91EF10095}.Release|Any CPU.Build.0 = Release|Any CPU
+               {EC395325-994F-47F6-8FC2-AC17EC452EDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {EC395325-994F-47F6-8FC2-AC17EC452EDA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {EC395325-994F-47F6-8FC2-AC17EC452EDA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {EC395325-994F-47F6-8FC2-AC17EC452EDA}.Release|Any CPU.Build.0 = Release|Any CPU
                {F03D161E-CC4D-4FE6-968A-04F884AB0939}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {F03D161E-CC4D-4FE6-968A-04F884AB0939}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {F03D161E-CC4D-4FE6-968A-04F884AB0939}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -111,7 +117,6 @@ Global
                {F042D024-3283-4E60-9A85-76E6BBBBB2C1}.Release|Any CPU.Build.0 = Release|Any CPU
        EndGlobalSection
        GlobalSection(MonoDevelopProperties) = preSolution
-               StartupItem = LongoMatch\LongoMatch.csproj
                Policies = $0
                $0.DotNetNamingPolicy = $1
                $1.DirectoryNamespaceAssociation = PrefixedHierarchical
diff --git a/Makefile.am b/Makefile.am
index 26c00ba..ef07cfd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,6 +12,7 @@ SUBDIRS = \
        libcesarplayer \
        oxyplot \
        LongoMatch.Core \
+       LongoMatch.DB \
        LongoMatch.Addins \
        LongoMatch.Multimedia \
        LongoMatch.Drawing \
diff --git a/Tests/DB/TestStorage.cs b/Tests/DB/TestStorage.cs
new file mode 100644
index 0000000..300eff5
--- /dev/null
+++ b/Tests/DB/TestStorage.cs
@@ -0,0 +1,160 @@
+//
+//  Copyright (C) 2015 Andoni Morales Alastruey
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+using NUnit.Framework;
+using System;
+using Couchbase.Lite;
+using LongoMatch.DB;
+using System.IO;
+using LongoMatch.Core.Common;
+using LongoMatch.Core.Store.Templates;
+using LongoMatch.Core.Store;
+using LongoMatch.Core.Interfaces;
+using Newtonsoft.Json.Linq;
+
+namespace Tests.DB
+{
+
+       class StorableImageTest : IStorable 
+       {
+               public Guid ID { get; set; }
+               public Image Image1 { get; set; }
+               public Image Image2 { get; set; }
+       }
+
+       [TestFixture ()]
+       public class TestStorage
+       {
+               Database db;
+               CouchbaseStorage storage;
+
+               [TestFixtureSetUp]
+               public void InitDB () {
+                       string dbPath = Path.Combine (Path.GetTempPath (), "TestDB");
+                       storage = new CouchbaseStorage (dbPath, "test-db");
+                       db = storage.Database;
+               }
+
+               [TestFixtureTearDown]
+               public void DeleteDB () {
+                       Directory.Delete (db.Manager.Directory, true);
+               }
+
+               [TearDown]
+               public void CleanDB () {
+                       foreach (var d in db.CreateAllDocumentsQuery ().Run()) {
+                               db.GetDocument (d.DocumentId).Delete ();
+                       }
+               }
+
+               [Test ()]
+               public void TestDocType ()
+               {
+                       StorableImageTest t = new StorableImageTest {
+                               ID = Guid.NewGuid (),
+                       };
+                       Document doc = db.CreateDocument ();
+                       JObject jo = DocumentsSerializer.SerializeObject (t, doc.CreateRevision (), true, 
null);
+                       Assert.AreEqual (t.ID, jo.Value<Guid> ("ID"));
+                       Assert.AreEqual ("StorableImageTest", jo.Value<string> ("DocType"));
+               }
+
+               [Test()]
+               public void TestSerializeImages () {
+                       Image img = Utils.LoadImageFromFile ();
+                       StorableImageTest t = new StorableImageTest {
+                               Image1 = img,
+                               Image2 = img,
+                               ID = Guid.NewGuid(),
+                       };
+                       Document doc = db.CreateDocument ();
+                       UnsavedRevision rev = doc.CreateRevision ();
+                       JObject jo = DocumentsSerializer.SerializeObject (t, rev, true, null);
+                       Assert.IsNotNull (jo ["ID"]);
+                       Assert.AreEqual ("attachment::Image1", jo ["Image1"].Value<string>());
+                       Assert.AreEqual ("attachment::Image2", jo ["Image2"].Value<string>());
+                       int i = 0;
+                       foreach (string name in rev.AttachmentNames) {
+                               i++;
+                               Assert.AreEqual ("Image" + i, name);
+                       }
+               }
+
+               [Test()]
+               public void TestDeserializeImages () {
+                       Image img = Utils.LoadImageFromFile ();
+                       StorableImageTest t = new StorableImageTest {
+                               Image1 = img,
+                               Image2 = img,
+                               ID = Guid.NewGuid(),
+                       };
+                       storage.Store (t);
+                       var test2 = storage.Retrieve<StorableImageTest> (t.ID);
+                       Assert.AreEqual (t.Image1.Width, test2.Image1.Width);
+                       Assert.AreEqual (t.Image1.Height, test2.Image1.Height);
+                       Assert.AreEqual (t.Image2.Width, test2.Image2.Width);
+                       Assert.AreEqual (t.Image2.Height, test2.Image2.Height);
+               }
+
+               [Test ()]
+               public void TestSaveDashboard ()
+               {
+                       Dashboard dashboard = Dashboard.DefaultTemplate (10);
+                       storage.Store (dashboard);
+                       Assert.AreEqual (1, db.DocumentCount);
+                       Assert.IsNotNull (db.GetExistingDocument (dashboard.ID.ToString()));
+               }
+
+               [Test ()]
+               public void TestLoadDashboard ()
+               {
+                       Dashboard dashboard = Dashboard.DefaultTemplate (10);
+                       dashboard.Image = dashboard.GoalBackground =
+                               dashboard.HalfFieldBackground = dashboard.FieldBackground = 
Utils.LoadImageFromFile();
+                       storage.Store (dashboard);
+                       Dashboard dashboard2 = storage.Retrieve<Dashboard> (dashboard.ID);
+                       Assert.IsNotNull (dashboard2);
+                       Assert.AreEqual (dashboard.ID, dashboard2.ID);
+                       Assert.AreEqual (dashboard.List.Count, dashboard2.List.Count);
+                       Assert.IsNotNull (dashboard2.Image);
+                       Assert.IsNotNull (dashboard2.FieldBackground);
+                       Assert.IsNotNull (dashboard2.HalfFieldBackground);
+                       Assert.IsNotNull (dashboard2.GoalBackground);
+                       Assert.AreEqual (16, dashboard2.Image.Width); 
+                       Assert.AreEqual (16, dashboard2.Image.Height); 
+               }
+
+               [Test ()]
+               public void TestSavePlayer ()
+               {
+                       Player player = new Player {Name = "andoni", Position = "runner",
+                               Number = 5, Birthday = new DateTime (1984, 6, 11),
+                               Nationality = "spanish", Height = 1.73f, Weight = 70,
+                               Playing = true, Mail = "test test", Color = Color.Red
+                       };
+                       storage.Store (player);
+                       Assert.AreEqual (1, db.DocumentCount);
+                       Assert.IsNotNull (db.GetExistingDocument (player.ID.ToString()));
+               }
+
+               [Test ()]
+               public void TestLoadPlayer ()
+               {
+               }
+       }
+}
+
diff --git a/Tests/Makefile.am b/Tests/Makefile.am
index 089a2d9..af4a08e 100644
--- a/Tests/Makefile.am
+++ b/Tests/Makefile.am
@@ -36,6 +36,8 @@ SOURCES = Core/Common/TestColor.cs \
        Core/Store/TestTimeNode.cs \
        Core/Store/TestTimelineEvent.cs \
        Core/Store/TestTimer.cs \
+       DB/TestDashboardDocument.cs \
+       Services/TestFileStorage.cs \
        Utils.cs
 
 RESOURCES = Core/dibujo.svg
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index a80ae63..10b5876 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -35,6 +35,10 @@
     <Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=b9a188c8922137c6">
       <Package>newtonsoft-json</Package>
     </Reference>
+    <Reference Include="Couchbase.Lite, Version=1.0.4.275, Culture=neutral">
+      <Package>couchbase-lite</Package>
+      <SpecificVersion>False</SpecificVersion>
+    </Reference>
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
@@ -54,7 +58,6 @@
     <Compile Include="Core\Store\TestTimelineEvent.cs" />
     <Compile Include="Core\Store\TestTimeNode.cs" />
     <Compile Include="Core\Common\TestColor.cs" />
-    <Compile Include="Core\Store\TestCoordinates.cs" />
     <Compile Include="Core\Store\Drawables\TestAngle.cs" />
     <Compile Include="Core\Store\Drawables\TestCross.cs" />
     <Compile Include="Core\Store\Drawables\TestDrawable.cs" />
@@ -73,6 +76,8 @@
     <Compile Include="Core\Store\Drawables\TestCircle.cs" />
     <Compile Include="Core\Store\Drawables\TestCounter.cs" />
     <Compile Include="Services\TestFileStorage.cs" />
+    <Compile Include="Core\Store\TestCoordinates.cs" />
+    <Compile Include="DB\TestStorage.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\LongoMatch.Core\LongoMatch.Core.csproj">
@@ -83,6 +88,10 @@
       <Project>{AA2793F9-3B72-4F34-9B34-2E0C18A8A960}</Project>
       <Name>LongoMatch.Services</Name>
     </ProjectReference>
+    <ProjectReference Include="..\LongoMatch.DB\LongoMatch.DB.csproj">
+      <Project>{EC395325-994F-47F6-8FC2-AC17EC452EDA}</Project>
+      <Name>LongoMatch.DB</Name>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="Core\dibujo.svg">
@@ -94,5 +103,6 @@
     <Folder Include="Core\Common\" />
     <Folder Include="Core\Store\Templates\" />
     <Folder Include="Services\" />
+    <Folder Include="DB\" />
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/build/build.environment.mk b/build/build.environment.mk
index c73e7fa..9231f83 100644
--- a/build/build.environment.mk
+++ b/build/build.environment.mk
@@ -23,7 +23,9 @@ LINK_DB40 = $(DB4O_LIBS)
 LINK_JSON = $(JSON_LIBS)
 LINK_NUNIT = $(NUNIT_LIBS)
 LINK_OSXYPLOT = -r:$(DIR_BIN)/OxyPlotMono.dll
+LINK_COUCHBASE = $(COUCHBASE_LIBS)
 LINK_LONGOMATCH_ADDINS = -r:$(DIR_BIN)/LongoMatch.Addins.dll
+LINK_LONGOMATCH_DB = -r:$(DIR_BIN)/LongoMatch.DB.dll
 LINK_LONGOMATCH_CORE = -r:$(DIR_BIN)/LongoMatch.Core.dll
 LINK_LONGOMATCH_MULTIMEDIA = -r:$(DIR_BIN)/LongoMatch.Multimedia.dll
 LINK_LONGOMATCH_GUI_MULTIMEDIA = -r:$(DIR_BIN)/LongoMatch.GUI.Multimedia.dll
@@ -166,11 +168,17 @@ REF_DEP_LONGOMATCH_PLUGINS_STATS = \
                      $(LINK_LONGOMATCH_GUI_HELPERS) \
                      $(LINK_LONGOMATCH_ADDINS)
 
+REF_DEP_LONGOMATCH_DB = \
+                     $(LINK_JSON) \
+                     $(LINK_COUCHBASE) \
+                     $(LINK_LONGOMATCH_CORE)
 
 REF_DEP_TESTS = \
                      $(LINK_LONGOMATCH_CORE) \
                      $(LINK_LONGOMATCH_SERVICES) \
+                     $(LINK_LONGOMATCH_DB) \
                      $(LINK_JSON) \
+                     $(LINK_COUCHBASE) \
                      $(LINK_NUNIT)
 
 DIR_BIN = $(top_builddir)/$(DEFAULT_BUILD_DIR)
diff --git a/configure.ac b/configure.ac
index 746ab15..c997fd0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -84,6 +84,10 @@ PKG_CHECK_MODULES([DB4O], [db4o],  [HAVE_DB4O=1], [HAVE_DB4O=0])
 AC_SUBST(DB4O_LIBS)
 PKG_CHECK_MODULES([MONO_ADDINS], [mono-addins])
 AC_SUBST(MONO_ADDINS_LIBS)
+PKG_CHECK_MODULES([COUCHBASE], [couchbase-lite])
+AC_SUBST(COUCHBASE_LIBS)
+COUCHBASE_LIBS_PATHS=`echo $COUCHBASE_LIBS | sed 's/-r://g'`
+AC_SUBST(COUCHBASE_LIBS_PATHS)
 
 AM_CONDITIONAL(WITH_MIGRATION_TOOL, [test "$HAVE_DB4O" -eq 1])
 
@@ -141,6 +145,7 @@ pkgconfig/longomatch-gui-helpers.pc
 pkgconfig/longomatch-oxyplot.pc
 
 LongoMatch.Addins/Makefile
+LongoMatch.DB/Makefile
 LongoMatch.Core/Makefile
 LongoMatch.Drawing/Makefile
 LongoMatch.Drawing.Cairo/Makefile


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