[tasque] Implement local file backend for new libtasque



commit 78fb9f49b04eeea6df040a0ba4f39bb86b716218
Author: Antonius Riha <antoniusriha gmail com>
Date:   Tue Mar 19 22:53:27 2013 +0100

    Implement local file backend for new libtasque

 src/Addins/Backends/Sqlite/Database.cs             |   29 ++-
 src/Addins/Backends/Sqlite/Extensions.cs           |   43 +++
 .../Backends/Sqlite/Gtk/SqlitePreferences.cs       |    3 +-
 .../Backends/Sqlite/Properties/AssemblyInfo.cs     |    3 +
 src/Addins/Backends/Sqlite/SqliteBackend.cs        |  382 +++++++-------------
 src/Addins/Backends/Sqlite/SqliteBackend.csproj    |   15 +-
 src/Addins/Backends/Sqlite/SqliteList.cs           |   80 ----
 src/Addins/Backends/Sqlite/SqliteNote.cs           |   35 --
 src/Addins/Backends/Sqlite/SqliteNoteRepository.cs |   66 ++++
 src/Addins/Backends/Sqlite/SqliteTask.cs           |  148 --------
 .../Backends/Sqlite/SqliteTaskListRepository.cs    |  159 ++++++++
 src/Addins/Backends/Sqlite/SqliteTaskRepository.cs |  255 +++++++++++++
 tasque.sln                                         |    1 +
 13 files changed, 688 insertions(+), 531 deletions(-)
---
diff --git a/src/Addins/Backends/Sqlite/Database.cs b/src/Addins/Backends/Sqlite/Database.cs
index ce0fce9..f1c37bb 100644
--- a/src/Addins/Backends/Sqlite/Database.cs
+++ b/src/Addins/Backends/Sqlite/Database.cs
@@ -1,15 +1,38 @@
+//
+// Database.cs
+//
+// Original header:
 // Database.cs created with MonoDevelop
-// User: calvin at 11:27 AM 2/19/2008
+// User: calvin at 11:27 AM 2/19/2008
 //
 // To change standard headers go to Edit->Preferences->Coding->Standard Headers
 //
-
+// Author:
+//       Unknown author
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
 using System;
 using Mono.Data.Sqlite;
 using System.IO;
 using Tasque;
 
-namespace Tasque.Backends.Sqlite
+namespace Tasque.Data.Sqlite
 {
        public class Database
        {
diff --git a/src/Addins/Backends/Sqlite/Extensions.cs b/src/Addins/Backends/Sqlite/Extensions.cs
new file mode 100644
index 0000000..74e0e86
--- /dev/null
+++ b/src/Addins/Backends/Sqlite/Extensions.cs
@@ -0,0 +1,43 @@
+//
+// Extensions.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using Mono.Data.Sqlite;
+
+namespace Tasque.Data.Sqlite
+{
+       public static class Extensions
+       {
+               public static void AddIdParameter (
+                       this SqliteParameterCollection source, ITasqueCore item)
+               {
+                       if (source == null)
+                               throw new NullReferenceException ("source");
+                       if (item == null)
+                               throw new ArgumentNullException ("item");
+                       source.AddWithValue ("@id", int.Parse (item.Id));
+               }
+       }
+}
diff --git a/src/Addins/Backends/Sqlite/Gtk/SqlitePreferences.cs 
b/src/Addins/Backends/Sqlite/Gtk/SqlitePreferences.cs
index 19689f8..9cecd9b 100644
--- a/src/Addins/Backends/Sqlite/Gtk/SqlitePreferences.cs
+++ b/src/Addins/Backends/Sqlite/Gtk/SqlitePreferences.cs
@@ -24,9 +24,8 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using Gtk;
-using Tasque.Backends;
 
-namespace Gtk.Tasque.Backends.Sqlite
+namespace Tasque.Data.Sqlite.Gtk
 {
        public class SqlitePreferences : Box, IBackendPreferences
        {
diff --git a/src/Addins/Backends/Sqlite/Properties/AssemblyInfo.cs 
b/src/Addins/Backends/Sqlite/Properties/AssemblyInfo.cs
index 1d0dad8..b592317 100644
--- a/src/Addins/Backends/Sqlite/Properties/AssemblyInfo.cs
+++ b/src/Addins/Backends/Sqlite/Properties/AssemblyInfo.cs
@@ -24,6 +24,9 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using System.Reflection;
+using Mono.Addins;
 
 [assembly: AssemblyTitle("SqliteBackend")]
 [assembly: AssemblyDescription("Sqlite backend for Tasque")]
+[assembly: Addin]
+[assembly: AddinDependency ("libtasque", "0.2.0")]
\ No newline at end of file
diff --git a/src/Addins/Backends/Sqlite/SqliteBackend.cs b/src/Addins/Backends/Sqlite/SqliteBackend.cs
index 23bbb82..900ffad 100644
--- a/src/Addins/Backends/Sqlite/SqliteBackend.cs
+++ b/src/Addins/Backends/Sqlite/SqliteBackend.cs
@@ -1,310 +1,176 @@
-// SqliteBackend.cs created with MonoDevelop
-// User: boyd at 7:10 AM 2/11/2008
+//
+// SqliteBackend.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
 using System;
 using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.ComponentModel;
-using System.Linq;
 using Mono.Data.Sqlite;
-using Tasque.Backends;
-using Gtk.Tasque.Backends.Sqlite;
+using Tasque.Data.Sqlite.Gtk;
+using Tasque.Utils;
 
-namespace Tasque.Backends.Sqlite
+namespace Tasque.Data.Sqlite
 {
-       public class SqliteBackend : IBackend
+       [BackendExtension ("Local file")]
+       public class SqliteBackend : IBackend2
        {
-               private bool initialized;
-               private bool configured = true;
+               public TasqueObjectFactory Factory { get; private set; }
 
-               ObservableCollection<Task> taskStore;
-               ObservableCollection<TaskList> taskListListStore;
-               ReadOnlyObservableCollection<Task> readOnlyTaskStore;
-               ReadOnlyObservableCollection<TaskList> readOnlyTaskListStore;
-               
-               TaskComparer taskComparer;
-               TaskListComparer taskListComparer;
-               
-               private Database db;
+               public bool IsInitialized { get; private set; }
 
-               public event EventHandler BackendInitialized;
-               public event EventHandler BackendSyncStarted;
-               public event EventHandler BackendSyncFinished;
-               
-               SqliteList defaultTaskList;
-               //SqliteTaskList workTaskList;
-               //SqliteTaskList projectsTaskList;
-               
-               public SqliteBackend ()
-               {
-                       initialized = false;
-                       taskStore = new ObservableCollection<Task> ();
-                       taskListListStore = new ObservableCollection<TaskList> ();
-                       readOnlyTaskStore = new ReadOnlyObservableCollection<Task> (taskStore);
-                       readOnlyTaskListStore
-                               = new ReadOnlyObservableCollection<TaskList> (taskListListStore);
-                       taskComparer = new TaskComparer ();
-                       taskListComparer = new TaskListComparer ();
-               }
-               
-               #region Public Properties
-               public string Name
-               {
-                       get { return "Local File"; } // TODO: Return something more usable to the user like, 
"Built-in" or whatever
-               }
-               
-               /// <value>
-               /// All the tasks including ITaskDivider items.
-               /// </value>
-               public ICollection<Task> Tasks
-               {
-                       get { return readOnlyTaskStore; }
-               }
-               
-               /// <value>
-               /// This returns all the task lists (taskLists) that exist.
-               /// </value>
-               public ICollection<TaskList> TaskLists
-               {
-                       get { return readOnlyTaskListStore; }
-               }
-               
-               /// <value>
-               /// Indication that the Sqlite backend is configured
-               /// </value>
-               public bool Configured 
-               {
-                       get { return configured; }
-               }
-               
-               
-               /// <value>
-               /// Inidication that the backend is initialized
-               /// </value>
-               public bool Initialized
-               {
-                       get { return initialized; }
-               }               
-               
-               public Database Database
-               {
-                       get { return db; }
+               public event EventHandler Initialized, Disposed;
+
+               bool IBackend2.IsConfigured { get { return IsInitialized; } }
+
+               IBackendPreferences IBackend2.Preferences {
+                       get { return new SqlitePreferences (); }
                }
                
-               public IBackendPreferences Preferences {
-                       get {
-                               // TODO: Replace this with returning null once things are going
-                               // so that the Preferences Dialog doesn't waste space.
-                               return new SqlitePreferences ();
-                       }
+               INoteRepository IRepositoryProvider<INoteRepository>.Repository {
+                       get { return noteRepo; }
                }
-               #endregion // Public Properties
                
-               #region Public Methods
-               public Task CreateTask (string taskName, TaskList taskList)
-               {
-                       // not sure what to do here with the taskList
-                       SqliteTask task = new SqliteTask (this, taskName);
-                       
-                       // Determine and set the task taskList
-                       if (taskList == null || taskList is Tasque.AllList)
-                               defaultTaskList.Add (task); // Default to work
-                       else
-                               taskList.Add (task);
-                       
-                       AddTask (task);
-                       task.PropertyChanged += HandlePropertyChanged;
-                       
-                       return task;
+               ITaskListRepository IRepositoryProvider<ITaskListRepository>
+                       .Repository { get { return taskListRepo; }
                }
                
-               public void DeleteTask(Task task)
-               {
-                       //string id = task.Id;
-                       task.Delete ();
-                       //string command = "delete from Tasks where id=" + id;
-                       //db.ExecuteNonQuery (command);
+               ITaskRepository IRepositoryProvider<ITaskRepository>.Repository {
+                       get { return taskRepo; }
                }
                
-               public void Refresh()
-               {}
-               
-               public void Initialize (IPreferences preferences)
+               void IBackend2.Initialize (IPreferences preferences)
                {
                        if (preferences == null)
                                throw new ArgumentNullException ("preferences");
-
-                       if(db == null)
-                               db = new Database();
-                               
-                       db.Open();
                        
-                       //
-                       // Add in the "All" TaskList
-                       //
-                       var allList = new AllList (this, preferences);
-                       AddTaskList (allList);
+                       database = new Database ();
+                       database.Open ();
+                       
+                       allList = new AllList (preferences);
 
-                       RefreshTaskLists();
-                       RefreshTasks();
+                       taskListRepo = new SqliteTaskListRepository (this, database);
+                       taskRepo = new SqliteTaskRepository (this, database);
+                       noteRepo = new SqliteNoteRepository (database);
 
-                       initialized = true;
-                       if(BackendInitialized != null) {
-                               BackendInitialized(null, null);
-                       }
+                       Factory = new TasqueObjectFactory (
+                               taskListRepo, taskRepo, noteRepo);
+
+                       IsInitialized = true;
+                       if (Initialized != null)
+                               Initialized (this, EventArgs.Empty);
                }
 
-               public void Dispose()
+               void IDisposable.Dispose ()
                {
                        if (disposed)
                                return;
 
-                       this.taskListListStore.Clear();
-                       this.taskStore.Clear();
-
-                       if (db != null)
-                               db.Close();
-                       db = null;
-                       initialized = false;
+                       database.Close ();
+                       database = null;
                        disposed = true;
-               }
-
-               /// <summary>
-               /// Given some text to be input into the database, do whatever
-               /// processing is required to make sure special characters are
-               /// escaped, etc.
-               /// </summary>
-               public string SanitizeText (string text)
-               {
-                       return text.Replace ("'", "''");
+                       if (Disposed != null)
+                               Disposed (this, EventArgs.Empty);
                }
                
-               #endregion // Public Methods
-               public void RefreshTaskLists()
+               IEnumerable<ITaskListCore> IBackend2.GetAll ()
                {
-                       SqliteList newTaskList;
-                       bool hasValues = false;
-                       
-                       string command = "SELECT id, name FROM Categories";
-                       SqliteCommand cmd = db.Connection.CreateCommand();
-                       cmd.CommandText = command;
-                       SqliteDataReader dataReader = cmd.ExecuteReader();
-                       while(dataReader.Read()) {
-                           int id = dataReader.GetInt32(0);
-                               var name = dataReader.GetString (1);
-                               hasValues = true;
-                               
-                               newTaskList = new SqliteList (this, id, name);
-                               if( (defaultTaskList == null) || (newTaskList.Name.CompareTo("Work") == 0) )
-                                       defaultTaskList = newTaskList;
-                               AddTaskList (newTaskList);
-                       }
-                       
-                       dataReader.Close();
-                       cmd.Dispose();
-
-                       if(!hasValues)
-                       {
-                               defaultTaskList = newTaskList = new SqliteList (this, "Work");
-                               AddTaskList (defaultTaskList);
+                       yield return allList;
 
-                               newTaskList = new SqliteList (this, "Personal");
-                               AddTaskList (newTaskList);
-                               
-                               newTaskList = new SqliteList (this, "Family");
-                               AddTaskList (newTaskList);
+                       ITaskListCore taskList;
+                       var hasValues = false;
 
-                               newTaskList = new SqliteList (this, "Project");
-                               AddTaskList (newTaskList);
+                       var command = "SELECT id, name FROM Categories";
+                       using (var cmd = new SqliteCommand (
+                               command, database.Connection)) {
+                               using (var dataReader = cmd.ExecuteReader ()) {
+                                       while (dataReader.Read ()) {
+                                               var id = dataReader.GetInt32 (0).ToString ();
+                                               var name = dataReader.GetString (1);
+                                               hasValues = true;
+                                               taskList = Factory.CreateTaskList (id, name);
+                                               yield return taskList;
+                                       }
+                               }
                        }
-               }
 
-               public void RefreshTasks()
-               {
-                       SqliteTask newTask;
-                       bool hasValues = false;
-                       
-                       string command = "SELECT id,Category,Name,DueDate,CompletionDate,Priority, State FROM 
Tasks";
-                       SqliteCommand cmd = db.Connection.CreateCommand();
-                       cmd.CommandText = command;
-                       SqliteDataReader dataReader = cmd.ExecuteReader();
-                       while(dataReader.Read()) {
-                               int id = dataReader.GetInt32(0);
-                               int taskList = dataReader.GetInt32(1);
-                               string name = dataReader.GetString(2);
-                               long dueDate = dataReader.GetInt64(3);
-                               long completionDate = dataReader.GetInt64(4);
-                               int priority = dataReader.GetInt32(5);
-                               int state = dataReader.GetInt32(6);
-                               
-                               hasValues = true;
-                               
-                               newTask = new SqliteTask (this, id, name, dueDate,
-                                                         completionDate, priority, state);
-                               var list = TaskLists.Single (l => {
-                                       var sqliteList = l as SqliteList;
-                                       if (sqliteList != null)
-                                               return sqliteList.ID == taskList;
-                                       return false;
-                               });
-                               list.Add (newTask);
-                               AddTask (newTask);
-                               newTask.PropertyChanged += HandlePropertyChanged;
-                       }
-                       
-                       dataReader.Close();
-                       cmd.Dispose();
-                       
-                       if(!hasValues)
-                       {
-                               newTask = new SqliteTask (this, "Create some tasks");
-                               defaultTaskList.Add (newTask);
-                               newTask.DueDate = DateTime.Now;
-                               newTask.Priority = TaskPriority.Medium;
-                               AddTask (newTask);
-                               newTask.PropertyChanged += HandlePropertyChanged;
+                       if (!hasValues) {
+                               var workCategory = CreateInitialTaskList ("Work");
+                               yield return workCategory;
+                               yield return CreateInitialTaskList ("Personal");
+                               yield return CreateInitialTaskList ("Family");
+                               yield return CreateInitialTaskList ("Project");
+
+                               var taskName = "Create some tasks";
+                               var insertCommand = string.Format (
+                                       "INSERT INTO Tasks" +
+                                       "(Name, DueDate, CompletionDate, Priority, State, " +
+                                       "Category, ExternalID) " +
+                                       "VALUES ('{0}', '{1}', '{2}', " +
+                                       "'{3}', '{4}', '{5}', '{6}');",
+                                       taskName, Database.FromDateTime (DateTime.MinValue),
+                                       Database.FromDateTime (DateTime.MinValue), 0,
+                                       (int)TaskState.Active, workCategory.Id, string.Empty);
+                               using (var cmd = new SqliteCommand (database.Connection)) {
+                                       cmd.CommandText = insertCommand;
+                                       cmd.ExecuteNonQuery ();
+                               }
                        }
                }
-
-               #region Private Methods
-               internal void DeleteTask (SqliteTask task)
+               
+               ITaskListCore IBackend2.GetBy (string id)
                {
-                       if (taskStore.Remove (task))
-                               task.PropertyChanged -= HandlePropertyChanged;
+                       throw new NotImplementedException ();
                }
-
-               void AddTaskList (TaskList taskList)
+               
+               void IBackend2.Create (ITaskListCore taskList)
                {
-                       var index = taskListListStore.Count;
-                       var valIdx = taskListListStore.Select ((val, idx) => new { val, idx })
-                               .FirstOrDefault (x => taskListComparer.Compare (x.val, taskList) > 0);
-                       if (valIdx != null)
-                               index = valIdx.idx;
-                       taskListListStore.Insert (index, taskList);
+                       throw new NotImplementedException ();
                }
                
-               void AddTask (SqliteTask task)
+               void IBackend2.Delete (ITaskListCore taskList)
                {
-                       var index = taskStore.Count;
-                       var valIdx = taskStore.Select ((val, idx) => new { val, idx })
-                               .FirstOrDefault (t => taskComparer.Compare (t.val, task) > 0);
-                       if (valIdx != null)
-                               index = valIdx.idx;
-                       
-                       taskStore.Insert (index, task);
+                       throw new NotImplementedException ();
                }
+               
+               event EventHandler IBackend2.NeedsConfiguration { add {} remove {} }
 
-               void HandlePropertyChanged (object sender, PropertyChangedEventArgs e)
+               ITaskListCore CreateInitialTaskList (string listName)
                {
-                       // when a property changes (any property atm), "reorder" tasks
-                       var task = (SqliteTask)sender;
-                       if (taskStore.Remove (task))
-                               AddTask (task);
+                       var command = "INSERT INTO Categories (Name, ExternalID) " +
+                               "values (@name, ''); SELECT last_insert_rowid();";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddWithValue ("@name", listName);
+                               var id = cmd.ExecuteScalar ().ToString ();
+                               return Factory.CreateTaskList (id, listName);
+                       }
                }
-               #endregion // Private Methods
-               
-               #region Event Handlers
-               #endregion // Event Handlers
 
                bool disposed;
+               Database database;
+               AllList allList;
+               ITaskListRepository taskListRepo;
+               ITaskRepository taskRepo;
+               INoteRepository noteRepo;
        }
 }
diff --git a/src/Addins/Backends/Sqlite/SqliteBackend.csproj b/src/Addins/Backends/Sqlite/SqliteBackend.csproj
index 827a164..4282343 100644
--- a/src/Addins/Backends/Sqlite/SqliteBackend.csproj
+++ b/src/Addins/Backends/Sqlite/SqliteBackend.csproj
@@ -8,7 +8,7 @@
     <ProjectGuid>{CCCC10A5-662D-4788-82D3-25689F3D4D4F}</ProjectGuid>
     <OutputType>Library</OutputType>
     <OutputPath>.</OutputPath>
-    <RootNamespace>Tasque.Backends.Sqlite</RootNamespace>
+    <RootNamespace>Tasque.Data.Sqlite</RootNamespace>
     <AssemblyName>SqliteBackend</AssemblyName>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
@@ -78,6 +78,10 @@
       <Package>gtk-sharp-2.0</Package>
     </Reference>
     <Reference Include="System.Core" />
+    <Reference Include="Mono.Addins, Version=0.6.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756">
+      <Private>False</Private>
+      <Package>mono-addins</Package>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\..\libtasque\libtasque.csproj">
@@ -86,16 +90,17 @@
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="SqliteTask.cs" />
-    <Compile Include="SqliteNote.cs" />
-    <Compile Include="SqliteBackend.cs" />
     <Compile Include="Database.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="..\..\..\..\build\CommonAssemblyInfo.cs">
       <Link>Properties\CommonAssemblyInfo.cs</Link>
     </Compile>
     <Compile Include="Gtk\SqlitePreferences.cs" />
-    <Compile Include="SqliteList.cs" />
+    <Compile Include="SqliteBackend.cs" />
+    <Compile Include="SqliteTaskListRepository.cs" />
+    <Compile Include="SqliteTaskRepository.cs" />
+    <Compile Include="SqliteNoteRepository.cs" />
+    <Compile Include="Extensions.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Properties\" />
diff --git a/src/Addins/Backends/Sqlite/SqliteNoteRepository.cs 
b/src/Addins/Backends/Sqlite/SqliteNoteRepository.cs
new file mode 100644
index 0000000..903c4ae
--- /dev/null
+++ b/src/Addins/Backends/Sqlite/SqliteNoteRepository.cs
@@ -0,0 +1,66 @@
+//
+// SqliteNoteRepository.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using Mono.Data.Sqlite;
+
+namespace Tasque.Data.Sqlite
+{
+       public class SqliteNoteRepository : INoteRepository
+       {
+               public SqliteNoteRepository (Database database)
+               {
+                       if (database == null)
+                               throw new ArgumentNullException ("database");
+                       this.database = database;
+               }
+
+               string INoteRepository.UpdateTitle (INoteCore note, string title)
+               {
+                       var command = "UPDATE Notes SET Name= name WHERE ID= id";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddWithValue ("@name", title);
+                               cmd.Parameters.AddIdParameter (note);
+                               cmd.ExecuteNonQuery ();
+                       }
+                       return title;
+               }
+
+               string INoteRepository.UpdateText (INoteCore note, string text)
+               {
+                       var command = "UPDATE Notes SET Text= text WHERE ID= id";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddWithValue ("@text", text);
+                               cmd.Parameters.AddIdParameter (note);
+                               cmd.ExecuteNonQuery ();
+                       }
+                       return text;
+               }
+
+               Database database;
+       }
+}
diff --git a/src/Addins/Backends/Sqlite/SqliteTaskListRepository.cs 
b/src/Addins/Backends/Sqlite/SqliteTaskListRepository.cs
new file mode 100644
index 0000000..dee3bf4
--- /dev/null
+++ b/src/Addins/Backends/Sqlite/SqliteTaskListRepository.cs
@@ -0,0 +1,159 @@
+//
+// SqliteTaskListRepository.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using Mono.Data.Sqlite;
+
+namespace Tasque.Data.Sqlite
+{
+       using TaskListTaskCollectionRepo =
+               ICollectionRepository<ITaskCore, ITaskListCore>;
+       
+       public class SqliteTaskListRepository : ITaskListRepository
+       {
+               public SqliteTaskListRepository (SqliteBackend backend,
+                                                Database database)
+               {
+                       if (backend == null)
+                               throw new ArgumentNullException ("backend");
+                       if (database == null)
+                               throw new ArgumentNullException ("database");
+                       this.backend = backend;
+                       this.database = database;
+               }
+               
+               bool ITaskListRepository.CanChangeName (ITaskListCore taskList)
+               {
+                       return false;
+               }
+
+               string ITaskListRepository.UpdateName (ITaskListCore taskList,
+                                                      string name)
+               {
+                       throw new NotSupportedException (
+                               "Cannot change the name of a task list.");
+               }
+
+               bool TaskListTaskCollectionRepo
+                       .SupportsSharingItemsWithOtherCollections { get { return false; }
+               }
+
+               IEnumerable<ITaskCore> TaskListTaskCollectionRepo.GetAll (
+                       ITaskListCore container)
+               {
+                       var command =
+                               "SELECT ID, Name, DueDate, CompletionDate, Priority, State " +
+                               "FROM Tasks WHERE Category= id;";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddIdParameter (container);
+                               using (var dataReader = cmd.ExecuteReader ()) {
+                                       while (dataReader.Read ()) {
+                                               var id = dataReader.GetInt32 (0).ToString ();
+                                               var name = dataReader.GetString (1);
+                                               var state = (TaskState)dataReader.GetInt32 (5);
+                                               var completionDate =
+                                                       Database.ToDateTime (dataReader.GetInt64 (3));
+
+                                               ITaskCore task;
+                                               if (state == TaskState.Active)
+                                                       task = backend.Factory.CreateTask (id, name);
+                                               else if (state == TaskState.Completed) {
+                                                       task = backend.Factory.CreateCompletedTask (
+                                                               id, name, completionDate);
+                                               } else {
+                                                       task = backend.Factory.CreateDiscardedTask (
+                                                               id, name);
+                                               }
+                                               task.Priority = (TaskPriority)dataReader.GetInt32 (4);
+                                               task.DueDate =
+                                                       Database.ToDateTime (dataReader.GetInt64 (2));
+
+                                               yield return task;
+                                       }
+                               }
+                       }
+               }
+
+               ITaskCore TaskListTaskCollectionRepo.GetBy (ITaskListCore container,
+                                                           string id)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               void TaskListTaskCollectionRepo.Add (ITaskListCore container,
+                                                    ITaskCore item)
+               {
+                       throw new NotSupportedException (
+                               "A task can only belong to one task list.");
+               }
+
+               void TaskListTaskCollectionRepo.AddNew (ITaskListCore container,
+                                                       ITaskCore item)
+               {
+                       var command =
+                               "INSERT INTO Tasks" +
+                               "(Name, DueDate, CompletionDate, Priority, State, " +
+                               "Category, ExternalID) " +
+                               "VALUES (@name, @dueDate, @completionDate, " +
+                               "@priority, @state, @catId, ''); " +
+                               "SELECT last_insert_rowid();";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddWithValue ("@name", item.Text);
+                               cmd.Parameters.AddWithValue ("@dueDate",
+                                       Database.FromDateTime (item.DueDate));
+                               cmd.Parameters.AddWithValue ("@completionDate",
+                                       Database.FromDateTime (DateTime.MinValue));
+                               cmd.Parameters.AddWithValue ("@priority", (int)item.Priority);
+                               cmd.Parameters.AddWithValue ("@state", (int)item.State);
+                               cmd.Parameters.AddWithValue ("@catId",
+                                                            int.Parse (container.Id));
+                               var id = cmd.ExecuteScalar ().ToString ();
+                               item.SetId (id);
+                       }
+               }
+
+               void TaskListTaskCollectionRepo.Remove (ITaskListCore container,
+                                                       ITaskCore item)
+               {
+                       var command = "DELETE FROM Tasks WHERE ID= id;";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddWithValue ("@id", int.Parse (item.Id));
+                               cmd.ExecuteNonQuery ();
+                       }
+               }
+
+               void TaskListTaskCollectionRepo.ClearAll (ITaskListCore container)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               SqliteBackend backend;
+               Database database;
+       }
+}
diff --git a/src/Addins/Backends/Sqlite/SqliteTaskRepository.cs 
b/src/Addins/Backends/Sqlite/SqliteTaskRepository.cs
new file mode 100644
index 0000000..8384807
--- /dev/null
+++ b/src/Addins/Backends/Sqlite/SqliteTaskRepository.cs
@@ -0,0 +1,255 @@
+//
+// SqliteTaskRepository.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using Mono.Data.Sqlite;
+
+namespace Tasque.Data.Sqlite
+{
+       using TaskTaskCollectionRepo = ICollectionRepository<ITaskCore, ITaskCore>;
+       using NoteCollectionRepo = ICollectionRepository<INoteCore, ITaskCore>;
+       
+       public class SqliteTaskRepository : ITaskRepository
+       {
+               const string NestedTasksErrMsg = "Nested tasks are not supported.";
+               
+               public SqliteTaskRepository (SqliteBackend backend, Database database)
+               {
+                       if (backend == null)
+                               throw new ArgumentNullException ("backend");
+                       if (database == null)
+                               throw new ArgumentNullException ("database");
+                       this.backend = backend;
+                       this.database = database;
+               }
+
+               DateTime ITaskRepository.UpdateDueDate (ITaskCore task, DateTime date)
+               {
+                       var command = "UPDATE Tasks SET DueDate= dueDate WHERE ID= id;";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddWithValue ("@dueDate",
+                                                            Database.FromDateTime (date));
+                               cmd.Parameters.AddIdParameter (task);
+                               cmd.ExecuteNonQuery ();
+                       }
+                       return date;
+               }
+
+               string ITaskRepository.UpdateText (ITaskCore task, string text)
+               {
+                       var command = "UPDATE Tasks SET Name= name WHERE ID= id;";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddWithValue ("@name", text);
+                               cmd.Parameters.AddIdParameter (task);
+                               cmd.ExecuteNonQuery ();
+                       }
+                       return text;
+               }
+
+               TaskPriority ITaskRepository.UpdatePriority (ITaskCore task,
+                                                            TaskPriority priority)
+               {
+                       var command = "UPDATE Tasks SET Priority= priority WHERE ID= id;";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddWithValue ("@priority", (int)priority);
+                               cmd.Parameters.AddIdParameter (task);
+                               cmd.ExecuteNonQuery ();
+                       }
+                       return priority;
+               }
+
+               void ITaskRepository.Activate (ITaskCore task)
+               {
+                       var command = "UPDATE Tasks SET State= state, " +
+                               "CompletionDate= completionDate WHERE ID= id;";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddWithValue ("@state", (int)TaskState.Active);
+                               cmd.Parameters.AddWithValue ("@completionDate",
+                                       Database.FromDateTime (DateTime.MinValue));
+                               cmd.Parameters.AddIdParameter (task);
+                               cmd.ExecuteNonQuery ();
+                       }
+               }
+
+               DateTime ITaskRepository.Complete (ITaskCore task,
+                                                  DateTime completionDate)
+               {
+                       var command = "UPDATE Tasks SET State= state, " +
+                               "CompletionDate= completionDate WHERE ID= id;";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddWithValue (
+                                       "@state", (int)TaskState.Completed);
+                               cmd.Parameters.AddWithValue ("@completionDate",
+                                       Database.FromDateTime (completionDate));
+                               cmd.Parameters.AddIdParameter (task);
+                               cmd.ExecuteNonQuery ();
+                       }
+                       return completionDate;
+               }
+
+               void ITaskRepository.Discard (ITaskCore task)
+               {
+                       var command = "UPDATE Tasks SET State= state WHERE ID= id;";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddWithValue (
+                                       "@state", (int)TaskState.Discarded);
+                               cmd.Parameters.AddIdParameter (task);
+                               cmd.ExecuteNonQuery ();
+                       }
+               }
+
+               bool ITaskRepository.SupportsNestedTasks { get { return false; } }
+
+               bool ITaskRepository.SupportsDiscarding { get { return true; } }
+
+               NoteSupport ITaskRepository.NoteSupport {
+                       get { return NoteSupport.Multiple; }
+               }
+               
+               #region Notes
+               
+               INoteCore ITaskRepository.UpdateNote (ITaskCore task, INoteCore note)
+               {
+                       throw new NotSupportedException (
+                               "This backend supports multiple notes.");
+               }
+
+               bool NoteCollectionRepo.SupportsSharingItemsWithOtherCollections {
+                       get { return false; }
+               }
+               
+               IEnumerable<INoteCore> NoteCollectionRepo.GetAll (ITaskCore container)
+               {
+                       var command =
+                               "SELECT ID, Name, Text FROM Notes WHERE Task= id;";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddIdParameter (container);
+                               using (var dataReader = cmd.ExecuteReader ()) {
+                                       var id = dataReader.GetInt32 (0).ToString ();
+                                       var name = dataReader.GetString (1);
+                                       var text = dataReader.GetString (2);
+                                       var note = backend.Factory.CreateNote (id);
+                                       note.Title = name;
+                                       note.Text = text;
+                                       yield return note;
+                               }
+                       }
+               }
+               
+               INoteCore NoteCollectionRepo.GetBy (ITaskCore container, string id)
+               {
+                       throw new NotImplementedException ();
+               }
+               
+               void NoteCollectionRepo.Add (ITaskCore container, INoteCore item)
+               {
+                       throw new NotSupportedException (
+                               "A note can only belong to a single task.");
+               }
+               
+               void NoteCollectionRepo.AddNew (ITaskCore container, INoteCore item)
+               {
+                       var command = "INSERT INTO Notes (Name, Text, Task)" +
+                               "VALUES (@name, @text, @id); SELECT last_insert_rowid();";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddWithValue ("@name", item.Title);
+                               cmd.Parameters.AddWithValue ("@text", item.Text);
+                               cmd.Parameters.AddIdParameter (container);
+                               var id = cmd.ExecuteScalar ().ToString ();
+                               item.SetId (id);
+                       }
+               }
+               
+               void NoteCollectionRepo.Remove (ITaskCore container, INoteCore item)
+               {
+                       var command = "DELETE FROM Notes WHERE ID= id;";
+                       using (var cmd = new SqliteCommand (database.Connection)) {
+                               cmd.CommandText = command;
+                               cmd.Parameters.AddIdParameter (item);
+                               cmd.ExecuteNonQuery ();
+                       }
+               }
+               
+               void NoteCollectionRepo.ClearAll (ITaskCore container)
+               {
+                       throw new NotImplementedException ();
+               }
+               
+               #endregion
+
+               #region Nested tasks
+
+               bool TaskTaskCollectionRepo.SupportsSharingItemsWithOtherCollections {
+                       get { throw new NotSupportedException (NestedTasksErrMsg); }
+               }
+
+               IEnumerable<ITaskCore> TaskTaskCollectionRepo.GetAll (
+                       ITaskCore container)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               ITaskCore TaskTaskCollectionRepo.GetBy (ITaskCore container, string id)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               void TaskTaskCollectionRepo.Add (ITaskCore container, ITaskCore item)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               void TaskTaskCollectionRepo.AddNew (ITaskCore container,
+                                                   ITaskCore item)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               void TaskTaskCollectionRepo.Remove (ITaskCore container,
+                                                   ITaskCore item)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               void TaskTaskCollectionRepo.ClearAll (ITaskCore container)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               #endregion
+
+               SqliteBackend backend;
+               Database database;
+       }
+}
diff --git a/tasque.sln b/tasque.sln
index 09b5795..e8f53a2 100644
--- a/tasque.sln
+++ b/tasque.sln
@@ -199,6 +199,7 @@ Global
                {CC8935CB-342C-4FDA-BAF1-24FA3EB53490}.MonoMacRelease|Any CPU.ActiveCfg = MonoMacRelease|Any 
CPU
                {CC8935CB-342C-4FDA-BAF1-24FA3EB53490}.MonoMacRelease|Any CPU.Build.0 = MonoMacRelease|Any CPU
                {CCCC10A5-662D-4788-82D3-25689F3D4D4F}.GtkLinuxDebug|Any CPU.ActiveCfg = GtkLinuxDebug|Any CPU
+               {CCCC10A5-662D-4788-82D3-25689F3D4D4F}.GtkLinuxDebug|Any CPU.Build.0 = GtkLinuxDebug|Any CPU
                {CCCC10A5-662D-4788-82D3-25689F3D4D4F}.GtkLinuxRelease|Any CPU.ActiveCfg = 
GtkLinuxRelease|Any CPU
                {CCCC10A5-662D-4788-82D3-25689F3D4D4F}.GtkLinuxRelease|Any CPU.Build.0 = GtkLinuxRelease|Any 
CPU
                {CCCC10A5-662D-4788-82D3-25689F3D4D4F}.GtkWinDebug|Any CPU.ActiveCfg = GtkWinDebug|Any CPU



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