[longomatch] Add the IStorable and IStorage interfaces



commit 61171b425698356789a58909bc27f02b5d1c7286
Author: Jorge Zapata <jorgeluis zapata gmail com>
Date:   Thu Mar 12 15:44:03 2015 +0100

    Add the IStorable and IStorage interfaces
    
    Create the first implementation of an IStorage and its unit test

 LongoMatch.Core/Interfaces/IStorable.cs        |   26 ++++++
 LongoMatch.Core/Interfaces/IStorage.cs         |   53 +++++++++++
 LongoMatch.Core/LongoMatch.Core.csproj         |    2 +
 LongoMatch.Services/LongoMatch.Services.csproj |    3 +
 LongoMatch.Services/Services/FileStorage.cs    |  114 ++++++++++++++++++++++++
 Tests/Services/TestFileStorage.cs              |   69 ++++++++++++++
 Tests/Tests.csproj                             |    8 +-
 7 files changed, 272 insertions(+), 3 deletions(-)
---
diff --git a/LongoMatch.Core/Interfaces/IStorable.cs b/LongoMatch.Core/Interfaces/IStorable.cs
new file mode 100644
index 0000000..343545c
--- /dev/null
+++ b/LongoMatch.Core/Interfaces/IStorable.cs
@@ -0,0 +1,26 @@
+//
+//  Copyright (C) 2015 jl
+//
+//  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;
+
+namespace LongoMatch.Core.Interfaces
+{
+       public interface IStorable : IIDObject
+       {
+       }
+}
+
diff --git a/LongoMatch.Core/Interfaces/IStorage.cs b/LongoMatch.Core/Interfaces/IStorage.cs
new file mode 100644
index 0000000..604f856
--- /dev/null
+++ b/LongoMatch.Core/Interfaces/IStorage.cs
@@ -0,0 +1,53 @@
+//
+//  Copyright (C) 2015 jl
+//
+//  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;
+
+namespace LongoMatch.Core.Interfaces
+{
+       public interface IStorage
+       {
+               /// <summary>
+               /// Retrieve every object of type T, where T must implement IStorable
+               /// </summary>
+               /// <typeparam name="T">The type of IStorable you want to retrieve.</typeparam>
+               List<T> RetrieveAll<T>() where T : IStorable;
+
+               /// <summary>
+               /// Store the specified object
+               /// </summary>
+               /// <param name="t">The object to store.</param>
+               /// <typeparam name="T">The type of the object to store.</typeparam>
+               void Store<T>(T t) where T : IStorable;
+
+               /// <summary>
+               /// Delete the specified object.
+               /// </summary>
+               /// <param name="t">The object to delete.</param>
+               /// <typeparam name="T">The type of the object to delete.</typeparam>
+               void Delete<T>(T t) where T : IStorable;
+
+               /// <summary>
+               /// Reset this instance. Basically will reset the storage to its initial state.
+               /// On a FS it can mean to remove every file. On a DB it can mean to remove every entry.
+               /// Make sure you know what you are doing before using this.
+               /// </summary>
+               void Reset();
+       }
+}
+
diff --git a/LongoMatch.Core/LongoMatch.Core.csproj b/LongoMatch.Core/LongoMatch.Core.csproj
index db11e13..500993c 100644
--- a/LongoMatch.Core/LongoMatch.Core.csproj
+++ b/LongoMatch.Core/LongoMatch.Core.csproj
@@ -135,6 +135,8 @@
     <Compile Include="Stats\PlayerStats.cs" />
     <Compile Include="Stats\TimerStats.cs" />
     <Compile Include="Common\Utils.cs" />
+    <Compile Include="Interfaces\IStorage.cs" />
+    <Compile Include="Interfaces\IStorable.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Common\" />
diff --git a/LongoMatch.Services/LongoMatch.Services.csproj b/LongoMatch.Services/LongoMatch.Services.csproj
index 8a2664d..360351a 100644
--- a/LongoMatch.Services/LongoMatch.Services.csproj
+++ b/LongoMatch.Services/LongoMatch.Services.csproj
@@ -8,6 +8,8 @@
     <RootNamespace>LongoMatch.Services</RootNamespace>
     <AssemblyName>LongoMatch.Services</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <ProductVersion>10.0.0</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -37,6 +39,7 @@
     <Compile Include="Services\DataBaseManager.cs" />
     <Compile Include="Services\ToolsManager.cs" />
     <Compile Include="Services\FileDB.cs" />
+    <Compile Include="Services\FileStorage.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="..\" />
diff --git a/LongoMatch.Services/Services/FileStorage.cs b/LongoMatch.Services/Services/FileStorage.cs
new file mode 100644
index 0000000..0e25c84
--- /dev/null
+++ b/LongoMatch.Services/Services/FileStorage.cs
@@ -0,0 +1,114 @@
+//
+//  Copyright (C) 2015 jl
+//
+//  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.IO;
+using System.Collections.Generic;
+using LongoMatch.Core.Interfaces;
+using LongoMatch.Core.Common;
+
+namespace LongoMatch.Services.Services
+{
+       public class FileStorage : IStorage
+       {
+               private string basePath;
+               private bool deleteOnDestroy;
+
+               public FileStorage (string basePath, bool deleteOnDestroy = false)
+               {
+                       this.basePath = basePath;
+                       this.deleteOnDestroy = deleteOnDestroy;
+                       // Make sure to create the directory
+                       if (!Directory.Exists (basePath)) {
+                               Log.Information ("Creating directory " + basePath);
+                               Directory.CreateDirectory (basePath);
+                       }
+               }
+
+               ~FileStorage()
+               {
+                       if (deleteOnDestroy)
+                               Reset();
+               }
+
+               private string ResolvePath<T> ()
+               {
+                       string typePath = Path.Combine(basePath, typeof(T).ToString());
+
+                       if (!Directory.Exists (typePath)) {
+                               Log.Information ("Creating directory " + typePath);
+                               Directory.CreateDirectory (typePath);
+                       }
+                       return typePath;
+               }
+
+               static private string GetExtension (Type t)
+               {
+                       // Add the different cases of t
+                       return ".json";
+               }
+
+               #region IStorage implementation
+
+               public List<T> RetrieveAll<T> () where T : IStorable
+               {
+                       List<T> l = new List<T> ();
+                       string typePath = ResolvePath<T>();
+                       string extension = GetExtension(typeof(T));
+
+                       // Get the name of the class and look for a folder on the
+                       // basePath with the same name
+                       foreach (string path in Directory.GetFiles (typePath, "*" + extension)) {
+                               T t = (T)Serializer.LoadSafe<T>(path);
+                               Log.Information ("Retrieving " + t.ID.ToString() + " at " + typePath);
+                               l.Add (t);
+                       }
+                       return l;
+               }
+
+               public void Store<T> (T t) where T : IStorable
+               {
+                       string typePath = ResolvePath<T>();
+                       string extension = GetExtension(typeof(T));
+
+                       // Save the object as a file on disk
+                       Log.Information ("Storing " + t.ID.ToString() + " at " + typePath);
+                       Serializer.Save<T>(t, Path.Combine(typePath, t.ID.ToString()) + extension);
+               }
+
+               public void Delete<T> (T t) where T : IStorable
+               {
+                       string typePath = ResolvePath<T>();
+                       string extension = GetExtension(typeof(T));
+
+                       try {
+                               Log.Information ("Deleting " + t.ID.ToString() + " at " + typePath);
+                               File.Delete (Path.Combine(typePath, t.ID.ToString()) + extension);
+                       } catch (Exception ex) {
+                               Log.Exception (ex);
+                       }
+               }
+
+               public void Reset()
+               {
+                       Log.Information ("Deleting " + basePath + " recursively");
+                       Directory.Delete(basePath, true);
+               }
+               #endregion
+       }
+}
+
diff --git a/Tests/Services/TestFileStorage.cs b/Tests/Services/TestFileStorage.cs
new file mode 100644
index 0000000..53f4018
--- /dev/null
+++ b/Tests/Services/TestFileStorage.cs
@@ -0,0 +1,69 @@
+//
+//  Copyright (C) 2015 jl
+//
+//  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 System.Collections.Generic;
+using LongoMatch.Services.Services;
+using LongoMatch.Core.Interfaces;
+
+namespace Tests.Services
+{
+       [TestFixture()]
+       public class TestFileStorage
+       {
+               private class TestStorable : IStorable
+               {
+                       public string memberString;
+
+                       public TestStorable(string memberString)
+                       {
+                               this.memberString = memberString;
+                               ID = Guid.NewGuid ();
+                       }
+
+                       public Guid ID {
+                               get;
+                               set;
+                       }
+               }
+
+               [Test()]
+               public void TestCase ()
+               {
+                       FileStorage fs = new FileStorage("/tmp/TestFileStorage/", true);
+                       TestStorable ts1 = new TestStorable("first");
+
+                       fs.Store<TestStorable>(ts1);
+                       List<TestStorable> lts = fs.RetrieveAll<TestStorable>();
+
+                       // Check that we have stored one object
+                       Assert.AreEqual(lts.Count, 1);
+                       TestStorable ts2 = lts[0];
+                       Assert.AreNotSame(ts2, null);
+
+                       // Check that the object is the same
+                       Assert.AreEqual(ts2.memberString, ts1.memberString);
+
+                       // Check that the storage is empty
+                       fs.Delete<TestStorable>(ts2);
+                       lts = fs.RetrieveAll<TestStorable>();
+                       Assert.AreEqual(lts.Count, 0);
+               }
+       }
+}
+
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 41814e8..a80ae63 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -8,6 +8,8 @@
     <RootNamespace>Tests</RootNamespace>
     <AssemblyName>Tests</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <ProductVersion>10.0.0</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -29,9 +31,7 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
-    <Reference Include="nunit.framework">
-      <Package>nunit</Package>
-    </Reference>
+    <Reference Include="nunit.framework" />
     <Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=b9a188c8922137c6">
       <Package>newtonsoft-json</Package>
     </Reference>
@@ -72,6 +72,7 @@
     <Compile Include="Core\Store\TestTag.cs" />
     <Compile Include="Core\Store\Drawables\TestCircle.cs" />
     <Compile Include="Core\Store\Drawables\TestCounter.cs" />
+    <Compile Include="Services\TestFileStorage.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\LongoMatch.Core\LongoMatch.Core.csproj">
@@ -92,5 +93,6 @@
     <Folder Include="Core\Store\" />
     <Folder Include="Core\Common\" />
     <Folder Include="Core\Store\Templates\" />
+    <Folder Include="Services\" />
   </ItemGroup>
 </Project>
\ No newline at end of file


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