WingMan – Rev 37

Subversion Repositories:
Rev:
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Mono.Data.Sqlite;

namespace WingMan.AutoCompletion
{
    public class AutoCompletion : IDisposable
    {
        public delegate void LoadFailed(object sender, AutoCompletionFailedEventArgs args);


        public delegate void SaveFailed(object sender, AutoCompletionFailedEventArgs args);

        public AutoCompletion()
        {
        }

        public AutoCompletion(TaskScheduler taskScheduler, CancellationToken cancellationToken) : this()
        {
            TaskScheduler = taskScheduler;
            CancellationToken = cancellationToken;
        }

        private TaskScheduler TaskScheduler { get; }
        private CancellationToken CancellationToken { get; }

        public void Dispose()
        {
        }

        public event SaveFailed OnSaveFailed;

        public event LoadFailed OnLoadFailed;

        public async Task Save(string name, AutoCompleteStringCollection autoCompleteStringCollection)
        {
            try
            {
                using (var sqliteConnection =
                    new SqliteConnection($"URI=file:{"Autocomplete.db"}"))
                {
                    await sqliteConnection.OpenAsync(CancellationToken);

                    // Create table if it does not exist.
                    using (var sqliteCommand =
                        new SqliteCommand($"CREATE TABLE IF NOT EXISTS {name} (data text UNIQUE NOT NULL)",
                            sqliteConnection))
                    {
                        using (var dbtransaction = sqliteConnection.BeginTransaction())
                        {
                            try
                            {
                                await sqliteCommand.ExecuteReaderAsync(CancellationToken);

                                dbtransaction.Commit();
                            }
                            catch
                            {
                                dbtransaction.Rollback();
                                throw;
                            }
                        }
                    }

                    // Add all items to the database.
                    await Task.Delay(0, CancellationToken).ContinueWith(async _ =>
                        {
                            foreach (var sourceItem in autoCompleteStringCollection)
                            {
                                var data = sourceItem.ToString();

                                using (var sqliteCommand =
                                    new SqliteCommand($"REPLACE INTO {name} (data) VALUES (:data)",
                                        sqliteConnection))
                                {
                                    sqliteCommand
                                        .Parameters
                                        .Add(new SqliteParameter("data", data));

                                    using (var dbtransaction = sqliteConnection.BeginTransaction())
                                    {
                                        try
                                        {
                                            await sqliteCommand.ExecuteReaderAsync(CancellationToken);

                                            dbtransaction.Commit();
                                        }
                                        catch
                                        {
                                            dbtransaction.Rollback();
                                            throw;
                                        }
                                    }
                                }
                            }
                        }, CancellationToken,
                        TaskContinuationOptions.None, TaskScheduler);
                }
            }
            catch (Exception ex)
            {
                await Task.Delay(0, CancellationToken).ContinueWith(_ => OnSaveFailed?.Invoke(this,
                        new AutoCompletionFailedEventArgs(AutoCompletionFailedType.Save, name, ex)), CancellationToken,
                    TaskContinuationOptions.None, TaskScheduler);
            }
        }

        public async Task Load(string name, AutoCompleteStringCollection autoCompleteStringCollection)
        {
            try
            {
                using (var sqliteConnection =
                    new SqliteConnection($"URI=file:{"Autocomplete.db"}"))
                {
                    await sqliteConnection.OpenAsync(CancellationToken);

                    // Create table if it does not exist.
                    using (var sqliteCommand =
                        new SqliteCommand($"CREATE TABLE IF NOT EXISTS {name} (data text UNIQUE NOT NULL)",
                            sqliteConnection))
                    {
                        using (var dbtransaction = sqliteConnection.BeginTransaction())
                        {
                            try
                            {
                                await sqliteCommand.ExecuteReaderAsync(CancellationToken);

                                dbtransaction.Commit();
                            }
                            catch
                            {
                                dbtransaction.Rollback();
                                throw;
                            }
                        }
                    }

                    using (var sqliteCommand =
                        new SqliteCommand($"SELECT data FROM {name}", sqliteConnection))
                    {
                        using (var dbtransaction = sqliteConnection.BeginTransaction())
                        {
                            try
                            {
                                using (var reader = await sqliteCommand.ExecuteReaderAsync(CancellationToken))
                                {
                                    while (await reader.ReadAsync(CancellationToken))
                                        for (var i = 0; i < reader.FieldCount; ++i)
                                        {
                                            var value = reader.GetString(i);
                                            if (string.IsNullOrEmpty(value))
                                                continue;

                                            await Task.Delay(0, CancellationToken).ContinueWith(
                                                _ => autoCompleteStringCollection.Add(value), CancellationToken,
                                                TaskContinuationOptions.None, TaskScheduler);
                                        }
                                }

                                dbtransaction.Commit();
                            }
                            catch
                            {
                                dbtransaction.Rollback();
                                throw;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                await Task.Delay(0, CancellationToken).ContinueWith(_ => OnLoadFailed?.Invoke(this,
                        new AutoCompletionFailedEventArgs(AutoCompletionFailedType.Load, name, ex)), CancellationToken,
                    TaskContinuationOptions.None, TaskScheduler);
            }
        }
    }
}