From f093f88eebdf39f3b5cfe51a9d7c8e98e5890dd8 Mon Sep 17 00:00:00 2001 From: jibedoubleve Date: Thu, 26 Mar 2020 11:31:43 +0100 Subject: [PATCH 1/5] Fix #57 - Fix wrong view in db and add db update system --- sql/scripts/update-0.1.sql | 27 ++++++ sql/views/statistics.sql | 6 -- .../Probel.Lanceur.Core.csproj | 1 + .../Services/ILogService.cs | 4 + .../Services/IUpdateService.cs | 13 +++ .../ServicesImpl/TraceLogger.cs | 24 +++-- .../EmbeddedResourceManager.cs | 12 ++- .../Probel.Lanceur.SQLiteDb.csproj | 8 +- .../Services/SQLiteDatabaseService.cs | 30 +++--- .../Services/SQLiteUpdateService.cs | 81 ++++++++++++++++ .../Services/UpdateManager.cs | 94 +++++++++++++++++++ src/Probel.Lanceur.Services/NLogLogger.cs | 8 ++ src/Probel.Lanceur/Bootstrapper.cs | 9 +- 13 files changed, 283 insertions(+), 34 deletions(-) create mode 100644 sql/scripts/update-0.1.sql delete mode 100644 sql/views/statistics.sql create mode 100644 src/Probel.Lanceur.Core/Services/IUpdateService.cs create mode 100644 src/Probel.Lanceur.SQLiteDb/Services/SQLiteUpdateService.cs create mode 100644 src/Probel.Lanceur.SQLiteDb/Services/UpdateManager.cs diff --git a/sql/scripts/update-0.1.sql b/sql/scripts/update-0.1.sql new file mode 100644 index 0000000..5876d60 --- /dev/null +++ b/sql/scripts/update-0.1.sql @@ -0,0 +1,27 @@ +/* + * Create tables and value to manage dabatase version. + * This data is used to know whether to make an update + * of the database + */ +create table settings ( + id integer primary key, + s_key text, + s_value text +); + +insert into settings (s_key, s_value) values ('db_version','0.1'); + +/* + * Fix history issue in the view + */ +drop view if exists stat_history; +create view stat_history as + select + s.id as id_keyword, + group_concat(sn.name, ', ') as keywords, + su.time_stamp as time_stamp + from + alias_usage su + inner join alias s on su.id_alias = s.id + inner join alias_name sn on s.id = sn.id_alias + group by su.time_stamp; \ No newline at end of file diff --git a/sql/views/statistics.sql b/sql/views/statistics.sql deleted file mode 100644 index cb7af44..0000000 --- a/sql/views/statistics.sql +++ /dev/null @@ -1,6 +0,0 @@ -drop view if exists stat_history; -create view stat_history as - select sn.name, su.time_stamp - from alias_usage su - inner join alias s on su.id_alias = s.id - inner join alias_name sn on s.id = sn.id_alias \ No newline at end of file diff --git a/src/Probel.Lanceur.Core/Probel.Lanceur.Core.csproj b/src/Probel.Lanceur.Core/Probel.Lanceur.Core.csproj index 95cbbfa..2e0e35f 100644 --- a/src/Probel.Lanceur.Core/Probel.Lanceur.Core.csproj +++ b/src/Probel.Lanceur.Core/Probel.Lanceur.Core.csproj @@ -91,6 +91,7 @@ + \ No newline at end of file diff --git a/src/Probel.Lanceur.Core/Services/ILogService.cs b/src/Probel.Lanceur.Core/Services/ILogService.cs index c2f064e..1d12953 100644 --- a/src/Probel.Lanceur.Core/Services/ILogService.cs +++ b/src/Probel.Lanceur.Core/Services/ILogService.cs @@ -12,6 +12,10 @@ public interface ILogService void Fatal(string message, Exception ex = null); + void Error(string message, Exception ex = null); + + void Info(string message); + void Trace(string message); void Warning(string message, Exception ex = null); diff --git a/src/Probel.Lanceur.Core/Services/IUpdateService.cs b/src/Probel.Lanceur.Core/Services/IUpdateService.cs new file mode 100644 index 0000000..e332087 --- /dev/null +++ b/src/Probel.Lanceur.Core/Services/IUpdateService.cs @@ -0,0 +1,13 @@ +namespace Probel.Lanceur.Core.Services +{ + public interface IUpdateService + { + #region Methods + + bool DoNeedUpdate(); + + void Update(); + + #endregion Methods + } +} \ No newline at end of file diff --git a/src/Probel.Lanceur.Core/ServicesImpl/TraceLogger.cs b/src/Probel.Lanceur.Core/ServicesImpl/TraceLogger.cs index 87e4381..46c3615 100644 --- a/src/Probel.Lanceur.Core/ServicesImpl/TraceLogger.cs +++ b/src/Probel.Lanceur.Core/ServicesImpl/TraceLogger.cs @@ -28,26 +28,30 @@ private enum Level #region Methods - private void WriteLine(Level level, string message, Exception ex = null) - { - var msg = string.Format(TEMPLATE, level.ToString().ToUpper(), message); - if (ex != null) - { - msg += Environment.NewLine + ex.ToString(); - } - OutputTrace.WriteLine(msg); - } - public void Debug(string message) => WriteLine(Level.Debug, message); public void Debug(Exception ex) => Debug(ex.ToString()); + public void Error(string message, Exception ex = null) => WriteLine(Level.Warning, message, ex); + public void Fatal(string message, Exception ex = null) => WriteLine(Level.Warning, message, ex); + public void Info(string message) => WriteLine(Level.Info, message); + public void Trace(string message) => WriteLine(Level.Trace, message); public void Warning(string message, Exception ex = null) => WriteLine(Level.Warning, message, ex); + private void WriteLine(Level level, string message, Exception ex = null) + { + var msg = string.Format(TEMPLATE, level.ToString().ToUpper(), message); + if (ex != null) + { + msg += Environment.NewLine + ex.ToString(); + } + OutputTrace.WriteLine(msg); + } + #endregion Methods } } \ No newline at end of file diff --git a/src/Probel.Lanceur.SQLiteDb/EmbeddedResourceManager.cs b/src/Probel.Lanceur.SQLiteDb/EmbeddedResourceManager.cs index efd3f6d..894ed3b 100644 --- a/src/Probel.Lanceur.SQLiteDb/EmbeddedResourceManager.cs +++ b/src/Probel.Lanceur.SQLiteDb/EmbeddedResourceManager.cs @@ -1,10 +1,12 @@ using System; +using System.Linq; +using System.Collections.Generic; using System.IO; using System.Reflection; namespace Probel.Lanceur.SQLiteDb { - public class EmbeddedResourceManager + internal class EmbeddedResourceManager { #region Fields @@ -52,6 +54,14 @@ public void ReadResourceAsString(string resourceName, Action OnResource) } } + public IEnumerable ListResources(string pattern) + { + var result = (from s in ExecutingAssembly.GetManifestResourceNames() + where s.Contains(pattern) + select s); + return result; + } + #endregion Methods } } \ No newline at end of file diff --git a/src/Probel.Lanceur.SQLiteDb/Probel.Lanceur.SQLiteDb.csproj b/src/Probel.Lanceur.SQLiteDb/Probel.Lanceur.SQLiteDb.csproj index b993cbe..1513391 100644 --- a/src/Probel.Lanceur.SQLiteDb/Probel.Lanceur.SQLiteDb.csproj +++ b/src/Probel.Lanceur.SQLiteDb/Probel.Lanceur.SQLiteDb.csproj @@ -64,6 +64,8 @@ + + @@ -75,7 +77,11 @@ Probel.Lanceur.Core - + + + Assets\Scripts\update-0.1.sql + + diff --git a/src/Probel.Lanceur.SQLiteDb/Services/SQLiteDatabaseService.cs b/src/Probel.Lanceur.SQLiteDb/Services/SQLiteDatabaseService.cs index 42b3fb1..255850f 100644 --- a/src/Probel.Lanceur.SQLiteDb/Services/SQLiteDatabaseService.cs +++ b/src/Probel.Lanceur.SQLiteDb/Services/SQLiteDatabaseService.cs @@ -34,11 +34,11 @@ public SQLiteDatabaseService(IReservedKeywordService keywordService, ILogService #region Methods - private DbConnection BuildConnectionString() => new SQLiteConnection(_connectionString); + private DbConnection BuildConnection() => new SQLiteConnection(_connectionString); public void Clear() { - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { var sql = @" delete from alias; @@ -71,7 +71,7 @@ insert into alias ( select last_insert_rowid() from alias;"; var sql2 = @"insert into alias_name(id_alias, name) values(@idAlias, @name)"; - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { var lastId = c.Query(sql, new { s.Arguments, s.FileName, s.Notes, s.RunAs, s.StartMode, s.IdSession }).FirstOrDefault(); @@ -91,7 +91,7 @@ public void Delete(Alias alias) { var sql = @"delete from alias_name where id_alias = @id"; var sql2 = @"delete from alias where id = @id"; - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { c.Execute(sql, new { alias.Id }); c.Execute(sql2, new { alias.Id }); @@ -100,7 +100,7 @@ public void Delete(Alias alias) public void Delete(AliasSession session) { - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { var queries = new string[] { @@ -114,7 +114,7 @@ public void Delete(AliasSession session) public IEnumerable GetNamesOf(Alias alias) { - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { var sql = @" select id as Id @@ -135,7 +135,7 @@ select id as id , notes as notes from alias_session where id = @sessionId"; - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { try { @@ -153,7 +153,7 @@ select id as id , name as name , notes as notes from alias_session "; - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { var result = c.Query(sql); return result.OrderBy(e => e.Name); @@ -177,7 +177,7 @@ from alias s inner join alias_name n on s.id = n.id_alias where n.name = @name"; - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { var result = c.Query(sql, new { name }) .FirstOrDefault(); @@ -194,7 +194,7 @@ from alias_name sn where s.id_session = @sessionId order by name"; - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { var result = c.Query(sql, new { sessionId }).ToList(); @@ -221,7 +221,7 @@ from alias s where s.id_session = @sessionId order by n.name "; - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { var result = c.Query(sql, new { sessionId }); return result ?? new List(); @@ -232,7 +232,7 @@ from alias s public void SetUsage(long idAlias) { - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { var sql = @"insert into alias_usage (id_alias, time_stamp) values (@idAlias, @now)"; c.Execute(sql, new { idAlias, now = DateTime.Now }); @@ -257,7 +257,7 @@ update alias_name set name = @name where id_alias = @id"; - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { c.Execute(sql, new { alias.Arguments, alias.FileName, alias.Notes, alias.RunAs, alias.StartMode, alias.Id, alias.WorkingDirectory }); c.Execute(sql2, new { alias.Name, alias.Id }); @@ -266,7 +266,7 @@ update alias_name public void Update(IEnumerable names) { - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { var sqlInsert = @"insert into alias_name (name, alias_id) values (@name, @aliasId)"; var sqlUpdate = @"update alias_name set name = @name where id = @id"; @@ -294,7 +294,7 @@ update alias_session name = @name, notes = @notes where id = @id"; - using (var c = BuildConnectionString()) + using (var c = BuildConnection()) { c.Execute(sql, new { session.Id, session.Name, session.Notes }); } diff --git a/src/Probel.Lanceur.SQLiteDb/Services/SQLiteUpdateService.cs b/src/Probel.Lanceur.SQLiteDb/Services/SQLiteUpdateService.cs new file mode 100644 index 0000000..74ce530 --- /dev/null +++ b/src/Probel.Lanceur.SQLiteDb/Services/SQLiteUpdateService.cs @@ -0,0 +1,81 @@ +using Dapper; +using Probel.Lanceur.Core.Services; +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Data.SQLite; +using System.Reflection; + +namespace Probel.Lanceur.SQLiteDb.Services +{ + public class SQLiteUpdateService : IUpdateService + { + #region Fields + + private readonly string _connectionString; + private readonly ILogService _logger; + + #endregion Fields + + #region Constructors + + public SQLiteUpdateService(ILogService logger) + { + _connectionString = new ConnectionStringManager().Get(); + _logger = logger; + } + + #endregion Constructors + + #region Methods + + public bool DoNeedUpdate() + { + var rm = new EmbeddedResourceManager(); + if (HasTableSettings()) + { + new UpdateManager(_connectionString, _logger).Update(); + return true; + } + else + { + var script = "Probel.Lanceur.SQLiteDb.Assets.Scripts.update-0.1.sql"; + _logger.Trace($"Do not has table 'settings'. Applying script '{script}'"); + + rm.ReadResourceAsString(script, content => ExecuteScript(content)); + + return false; + } + } + + public void Update() => throw new NotImplementedException(); + + private DbConnection BuildConnection() => new SQLiteConnection(_connectionString); + + private void ExecuteScript(string content) + { + try + { + using (var c = BuildConnection()) + { + c.Execute(content); + } + } + catch (Exception ex) + { + _logger.Error($"An error occured while updating database. {ex.Message}", ex); + } + } + + private bool HasTableSettings() + { + using (var c = BuildConnection()) + { + var sql = "select count(name) from sqlite_master where type = 'table' and name = 'settings';"; + return (long)c.ExecuteScalar(sql) > 0; + } + } + + #endregion Methods + } +} \ No newline at end of file diff --git a/src/Probel.Lanceur.SQLiteDb/Services/UpdateManager.cs b/src/Probel.Lanceur.SQLiteDb/Services/UpdateManager.cs new file mode 100644 index 0000000..b5de235 --- /dev/null +++ b/src/Probel.Lanceur.SQLiteDb/Services/UpdateManager.cs @@ -0,0 +1,94 @@ +using Dapper; +using Probel.Lanceur.Core.Services; +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Data.SQLite; +using System.Text.RegularExpressions; + +namespace Probel.Lanceur.SQLiteDb.Services +{ + public class UpdateManager + { + #region Fields + + public const string Pattern = "Probel.Lanceur.SQLiteDb.Assets.Scripts."; + private readonly string _connectionString; + private readonly ILogService _logger; + private EmbeddedResourceManager _resManager = new EmbeddedResourceManager(); + + #endregion Fields + + #region Constructors + + public UpdateManager(string connectionString, ILogService logger) + { + _logger = logger; + _connectionString = connectionString; + } + + #endregion Constructors + + #region Methods + + public void Update() + { + var cur = GetCurrentVersion(); + + using (var c = BuildConnection()) + { + foreach (var res in GetResources()) + { + _logger.Trace($"Current version is {cur}"); + if (cur < res.Key) + { + _logger.Info($"Updating database. Current version is {cur}. Executing script version '{res.Key}'"); + Execute(res.Value, c); + } + } + } + } + + private void Execute(string value, DbConnection conn) + { + _resManager.ReadResourceAsString(value, sql => conn.Execute(sql)); + } + + private DbConnection BuildConnection() => new SQLiteConnection(_connectionString); + + private Version GetCurrentVersion() + { + try + { + var sql = "select s_value from settings where s_key = 'db_version'"; + using (var c = BuildConnection()) + { + var r = (string)c.ExecuteScalar(sql); + return Version.Parse(r); + } + } + catch (Exception ex) + { + var msg = $"Impossible to retrieve the version of the database. Check inner exception for further information."; + throw new InvalidOperationException(msg, ex); + } + } + + private IDictionary GetResources() + { + var dico = new Dictionary(); + var resources = _resManager.ListResources(Pattern); + var regex = new Regex(@"Probel\.Lanceur\.SQLiteDb\.Assets\.Scripts\.update-(?\d{1,2}\.\d{1,2})\.sql"); + + foreach (var r in resources) + { + var v = Version.Parse(regex.Match(r)?.Groups["version"]?.Value ?? string.Empty); + dico.Add(v, r); + } + + return dico; + } + + #endregion Methods + } +} \ No newline at end of file diff --git a/src/Probel.Lanceur.Services/NLogLogger.cs b/src/Probel.Lanceur.Services/NLogLogger.cs index 917f574..f4a64e1 100644 --- a/src/Probel.Lanceur.Services/NLogLogger.cs +++ b/src/Probel.Lanceur.Services/NLogLogger.cs @@ -18,12 +18,20 @@ public class NLogLogger : ILogService public void Debug(Exception ex) => _logger.Debug(ex); + public void Error(string message, Exception ex = null) + { + if (ex != null) { _logger.Error(ex, message); } + else { _logger.Error(message); } + } + public void Fatal(string message, Exception ex = null) { if (ex != null) { _logger.Fatal(ex, message); } else { _logger.Fatal(message); } } + public void Info(string message) => _logger.Info(message); + public void Trace(string message) => _logger.Trace(message); public void Warning(string message, Exception ex = null) diff --git a/src/Probel.Lanceur/Bootstrapper.cs b/src/Probel.Lanceur/Bootstrapper.cs index c6e5b81..79d9206 100644 --- a/src/Probel.Lanceur/Bootstrapper.cs +++ b/src/Probel.Lanceur/Bootstrapper.cs @@ -65,6 +65,7 @@ protected override void Configure() _container.RegisterType(); _container.RegisterType(); _container.RegisterType(); + _container.RegisterType(); //UI _container.RegisterType(); @@ -82,7 +83,13 @@ protected override void Configure() protected override object GetInstance(Type service, string key) => _container.Resolve(service, key); - protected override void OnStartup(object sender, StartupEventArgs e) => DisplayRootViewFor(); + protected override void OnStartup(object sender, StartupEventArgs e) + { + var u =_container.Resolve(); + u.DoNeedUpdate(); + + DisplayRootViewFor(); + } protected override void OnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { From a8ec6edeff6cc960c4348509f871a40a9dd7ec0e Mon Sep 17 00:00:00 2001 From: jibedoubleve Date: Fri, 27 Mar 2020 10:06:57 +0100 Subject: [PATCH 2/5] Close #58 - Refactoring of keywords --- src/Probel.Lanceur.Core/Constants/Enums.cs | 30 +++++----- .../Probel.Lanceur.Core.csproj | 1 + .../Services/IKeywordLoader.cs | 15 +++++ .../Services/IReservedKeywordService.cs | 6 +- .../MacroManagement/MacroAttribute.cs | 10 +++- .../ReservedKeywordService.cs | 34 ++++------- src/Probel.Lanceur/Actions/ActionManager.cs | 36 +++-------- src/Probel.Lanceur/Actions/AddAction.cs | 3 + src/Probel.Lanceur/Actions/BaseUiAction.cs | 12 ++-- src/Probel.Lanceur/Actions/KeywordLoader.cs | 59 +++++++++++++++++++ src/Probel.Lanceur/Bootstrapper.cs | 1 + src/Probel.Lanceur/Probel.Lanceur.csproj | 1 + .../ViewModels/MainViewModel.cs | 2 +- 13 files changed, 133 insertions(+), 77 deletions(-) create mode 100644 src/Probel.Lanceur.Core/Services/IKeywordLoader.cs create mode 100644 src/Probel.Lanceur/Actions/KeywordLoader.cs diff --git a/src/Probel.Lanceur.Core/Constants/Enums.cs b/src/Probel.Lanceur.Core/Constants/Enums.cs index 468cdd1..5929b70 100644 --- a/src/Probel.Lanceur.Core/Constants/Enums.cs +++ b/src/Probel.Lanceur.Core/Constants/Enums.cs @@ -1,20 +1,20 @@ namespace Probel.Lanceur.Core.Constants { - public enum Keywords - { - Add, - Corner, - Help, - Hide, - Jot, - Quit, - Savepos, - Setup, - Import, - Clear, - Echo, - Version, - } + //public enum Keywords + //{ + // Add, + // Corner, + // Help, + // Hide, + // Jot, + // Quit, + // Savepos, + // Setup, + // Import, + // Clear, + // Echo, + // Version, + //} public enum RunAs { diff --git a/src/Probel.Lanceur.Core/Probel.Lanceur.Core.csproj b/src/Probel.Lanceur.Core/Probel.Lanceur.Core.csproj index 2e0e35f..6f6c804 100644 --- a/src/Probel.Lanceur.Core/Probel.Lanceur.Core.csproj +++ b/src/Probel.Lanceur.Core/Probel.Lanceur.Core.csproj @@ -46,6 +46,7 @@ Properties\Version.cs + diff --git a/src/Probel.Lanceur.Core/Services/IKeywordLoader.cs b/src/Probel.Lanceur.Core/Services/IKeywordLoader.cs new file mode 100644 index 0000000..01b58da --- /dev/null +++ b/src/Probel.Lanceur.Core/Services/IKeywordLoader.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace Probel.Lanceur.Core.Services +{ + public interface IKeywordLoader + { + #region Methods + + bool Contains(string keyword); + + IEnumerable GetDefinedKeywords(); + + #endregion Methods + } +} \ No newline at end of file diff --git a/src/Probel.Lanceur.Core/Services/IReservedKeywordService.cs b/src/Probel.Lanceur.Core/Services/IReservedKeywordService.cs index b599d09..4cef495 100644 --- a/src/Probel.Lanceur.Core/Services/IReservedKeywordService.cs +++ b/src/Probel.Lanceur.Core/Services/IReservedKeywordService.cs @@ -1,14 +1,14 @@ -using Probel.Lanceur.Core.Constants; -using System; +using System; using System.Collections.Generic; namespace Probel.Lanceur.Core.Services { + public interface IReservedKeywordService { #region Methods - void Bind(Keywords cmd, Action bindedAction); + void Bind(string keyword, Action bindedAction); void ExecuteActionFor(string name, string arg); diff --git a/src/Probel.Lanceur.Core/ServicesImpl/MacroManagement/MacroAttribute.cs b/src/Probel.Lanceur.Core/ServicesImpl/MacroManagement/MacroAttribute.cs index 26535fc..723681a 100644 --- a/src/Probel.Lanceur.Core/ServicesImpl/MacroManagement/MacroAttribute.cs +++ b/src/Probel.Lanceur.Core/ServicesImpl/MacroManagement/MacroAttribute.cs @@ -2,9 +2,17 @@ namespace Probel.Lanceur.Core.ServicesImpl.MacroManagement { - internal class MacroAttribute : Attribute + /// + /// A macro if a list of alias to be run sequentially. + /// + internal sealed class MacroAttribute : Attribute { + #region Fields + private readonly string _name; + + #endregion Fields + #region Constructors public MacroAttribute(string name) diff --git a/src/Probel.Lanceur.Services/ReservedKeywordService.cs b/src/Probel.Lanceur.Services/ReservedKeywordService.cs index a929a36..d5389a0 100644 --- a/src/Probel.Lanceur.Services/ReservedKeywordService.cs +++ b/src/Probel.Lanceur.Services/ReservedKeywordService.cs @@ -1,5 +1,4 @@ -using Probel.Lanceur.Core.Constants; -using Probel.Lanceur.Core.Services; +using Probel.Lanceur.Core.Services; using System; using System.Collections.Generic; @@ -10,6 +9,7 @@ public class ReservedKeywordService : IReservedKeywordService #region Fields private static readonly Dictionary> _reservedKeywords = new Dictionary>(); + private readonly IKeywordLoader _keywordLoader; private static ILogService _log; private IList _keywords = null; @@ -18,28 +18,27 @@ public class ReservedKeywordService : IReservedKeywordService #region Constructors - static ReservedKeywordService() + public ReservedKeywordService(ILogService log, IKeywordLoader keywordLoader) { - foreach (var keyword in Enum.GetValues(typeof(Keywords))) - { - var key = keyword.ToString().ToUpper(); - _reservedKeywords.Add(key, arg => _log.Trace($"Unbinded action for {key}")); - } + _keywordLoader = keywordLoader; + _log = log; } - public ReservedKeywordService(ILogService log) => _log = log; - #endregion Constructors #region Methods - public void Bind(Keywords cmd, Action bindedAction) + public void Bind(string keyword, Action bindedAction) { - var c = cmd.ToString().ToUpper(); + var c = keyword.ToUpper(); if (_reservedKeywords.ContainsKey(c)) { _reservedKeywords[c] = bindedAction; } + else if(_keywordLoader.Contains(keyword)) + { + _reservedKeywords.Add(c, bindedAction); + } } /// @@ -57,16 +56,7 @@ public void ExecuteActionFor(string name, string arg) } } - public IEnumerable GetReservedKeywords() - { - if (_keywords == null) - { - _keywords = new List(); - var names = Enum.GetNames(typeof(Keywords)); - foreach (var name in names) { _keywords.Add(name.ToLower()); } - } - return _keywords; - } + public IEnumerable GetReservedKeywords() => _keywordLoader.GetDefinedKeywords(); public bool IsReserved(string name) => _reservedKeywords.ContainsKey(name); diff --git a/src/Probel.Lanceur/Actions/ActionManager.cs b/src/Probel.Lanceur/Actions/ActionManager.cs index 23fd7c4..2cf1a89 100644 --- a/src/Probel.Lanceur/Actions/ActionManager.cs +++ b/src/Probel.Lanceur/Actions/ActionManager.cs @@ -1,7 +1,5 @@ -using Probel.Lanceur.Core.Constants; -using Probel.Lanceur.Core.Services; +using Probel.Lanceur.Core.Services; using System; -using System.Collections.Generic; using System.Linq; using System.Reflection; using Unity; @@ -12,12 +10,11 @@ internal class ActionManager { #region Fields + public readonly ILogService _logger; private readonly IUnityContainer _container; private readonly IReservedKeywordService _reservedKeywordService; - public readonly ILogService _logger; - #endregion Fields #region Constructors @@ -34,27 +31,6 @@ public ActionManager(IReservedKeywordService reservedKeywordService, IUnityConta #region Methods - private static IEnumerable GetKeyword(string name) - { - return (from a in Enum.GetValues(typeof(Keywords)).Cast() - where a.ToString().ToLower() == name.ToLower() - select a); - } - - private Keywords GetActionName(Type type) - { - var name = type.Name.Replace("Action", ""); - var action = GetKeyword(name); - - if (action.Count() == 0) - { - var r = GetKeyword(type.GetCustomAttribute().Action); - if (r.Count() > 0) { return r.First(); } - else { throw new NotSupportedException($"The action '{name}' does not exist or is not supported. Did you forget to add it in the enum '{typeof(Keywords)}'?"); } - } - else { return action.First(); } - } - public void Bind() { var types = from t in Assembly.GetAssembly(typeof(IUiAction)).GetTypes() @@ -62,7 +38,7 @@ where t.GetCustomAttribute() != null select t; foreach (var type in types) { - var actionName = GetActionName(type); + var actionName = GetActionName(type).ToUpper(); _logger.Trace($"Found type '{type.Name}' for action '{actionName}'"); var action = (IUiAction)Activator.CreateInstance(type); @@ -71,6 +47,12 @@ where t.GetCustomAttribute() != null } } + private string GetActionName(Type type) + { + var name = type.Name.Replace("Action", ""); + return name; + } + #endregion Methods } } \ No newline at end of file diff --git a/src/Probel.Lanceur/Actions/AddAction.cs b/src/Probel.Lanceur/Actions/AddAction.cs index 84bf79d..e17fa06 100644 --- a/src/Probel.Lanceur/Actions/AddAction.cs +++ b/src/Probel.Lanceur/Actions/AddAction.cs @@ -16,6 +16,9 @@ protected override void Configure() protected override void DoExecute(string arg) { + var keywords = Container.Resolve(); + if (keywords.Contains(arg)) { return; } + using (DeactivateHotKey.During()) { var vm = Container.Resolve(); diff --git a/src/Probel.Lanceur/Actions/BaseUiAction.cs b/src/Probel.Lanceur/Actions/BaseUiAction.cs index 5b8623e..b17396e 100644 --- a/src/Probel.Lanceur/Actions/BaseUiAction.cs +++ b/src/Probel.Lanceur/Actions/BaseUiAction.cs @@ -20,14 +20,6 @@ public abstract class BaseUiAction : IUiAction #region Methods - private void DoConfigure() - { - if (_isConfigured == false) { Configure(); } - } - - protected abstract void Configure(); - - protected abstract void DoExecute(string arg); public void Execute(string arg) { Configure(); @@ -41,6 +33,10 @@ public IUiAction With(IUnityContainer container) return this; } + protected abstract void Configure(); + + protected abstract void DoExecute(string arg); + #endregion Methods } } \ No newline at end of file diff --git a/src/Probel.Lanceur/Actions/KeywordLoader.cs b/src/Probel.Lanceur/Actions/KeywordLoader.cs new file mode 100644 index 0000000..4980701 --- /dev/null +++ b/src/Probel.Lanceur/Actions/KeywordLoader.cs @@ -0,0 +1,59 @@ +using Probel.Lanceur.Core.Services; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace Probel.Lanceur.Actions +{ + public class KeywordLoader : IKeywordLoader + { + #region Fields + + private readonly ILogService _logger; + private List _keywords; + + #endregion Fields + + #region Constructors + + public KeywordLoader(ILogService logger) + { + _logger = logger; + } + + #endregion Constructors + + #region Methods + + public bool Contains(string keyword) + { + if (_keywords == null) { GetDefinedKeywords(); } + + var exists = (from k in _keywords + where keyword.ToLower() == k.ToLower() + select k).Any(); + return exists; + } + + public IEnumerable GetDefinedKeywords() + { + var types = from t in Assembly.GetAssembly(typeof(IUiAction)).GetTypes() + where t.GetCustomAttribute() != null + select t; + + if (_keywords == null) + { + _keywords = new List(); + foreach (var type in types) + { + var actionName = type.Name.Replace("Action", "").ToLower(); + _logger.Trace($"Found type '{type.Name}' for action '{actionName}'"); + _keywords.Add(actionName); + } + } + return _keywords; + } + + #endregion Methods + } +} \ No newline at end of file diff --git a/src/Probel.Lanceur/Bootstrapper.cs b/src/Probel.Lanceur/Bootstrapper.cs index 79d9206..8ad592f 100644 --- a/src/Probel.Lanceur/Bootstrapper.cs +++ b/src/Probel.Lanceur/Bootstrapper.cs @@ -66,6 +66,7 @@ protected override void Configure() _container.RegisterType(); _container.RegisterType(); _container.RegisterType(); + _container.RegisterType(); //UI _container.RegisterType(); diff --git a/src/Probel.Lanceur/Probel.Lanceur.csproj b/src/Probel.Lanceur/Probel.Lanceur.csproj index 01f903b..ac26460 100644 --- a/src/Probel.Lanceur/Probel.Lanceur.csproj +++ b/src/Probel.Lanceur/Probel.Lanceur.csproj @@ -177,6 +177,7 @@ + diff --git a/src/Probel.Lanceur/ViewModels/MainViewModel.cs b/src/Probel.Lanceur/ViewModels/MainViewModel.cs index 330f304..fcf0af2 100644 --- a/src/Probel.Lanceur/ViewModels/MainViewModel.cs +++ b/src/Probel.Lanceur/ViewModels/MainViewModel.cs @@ -116,7 +116,7 @@ public bool ExecuteText(string cmdLine) try { return _aliasService.Execute(cmdLine); } catch (Exception ex) { - /* I swallow the error as this crash should'nt crash the application + /* I swallow the error as this crash shouldn't crash the application * I log and continue without any other warning. */ LogService.Warning($"An error occured while trying to execute the alias '{cmdLine}'", ex); From d5026118b7a518ec599ee88e50e8638304794114 Mon Sep 17 00:00:00 2001 From: jibedoubleve Date: Fri, 27 Mar 2020 12:46:18 +0100 Subject: [PATCH 3/5] Fix #61 Fix #63 - Fix crash on 64 bits apps and improve crash handling --- build.cake | 3 ++- src/Probel.Lanceur/Bootstrapper.cs | 3 ++- .../Probel.Lanceur.UnitTest/Probel.Lanceur.UnitTest.csproj | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/build.cake b/build.cake index 7449a1f..5216f5f 100644 --- a/build.cake +++ b/build.cake @@ -79,7 +79,8 @@ Task("Build") .Does(() => { var msBuildSettings = new MSBuildSettings { Verbosity = verbosity, - Configuration = configuration + Configuration = configuration, + PlatformTarget = PlatformTarget.x64 }; MSBuild(solution, msBuildSettings diff --git a/src/Probel.Lanceur/Bootstrapper.cs b/src/Probel.Lanceur/Bootstrapper.cs index 8ad592f..6c83f62 100644 --- a/src/Probel.Lanceur/Bootstrapper.cs +++ b/src/Probel.Lanceur/Bootstrapper.cs @@ -86,7 +86,7 @@ protected override void Configure() protected override void OnStartup(object sender, StartupEventArgs e) { - var u =_container.Resolve(); + var u = _container.Resolve(); u.DoNeedUpdate(); DisplayRootViewFor(); @@ -96,6 +96,7 @@ protected override void OnUnhandledException(object sender, DispatcherUnhandledE { MessageBox.Show($"Unexpected crash occured: {e.Exception.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); _container.Resolve().Fatal($"Unexpected crash occured: {e.Exception.Message}", e.Exception); + e.Handled = true; base.OnUnhandledException(sender, e); } diff --git a/src/Tests/Probel.Lanceur.UnitTest/Probel.Lanceur.UnitTest.csproj b/src/Tests/Probel.Lanceur.UnitTest/Probel.Lanceur.UnitTest.csproj index 85b2aca..80805ee 100644 --- a/src/Tests/Probel.Lanceur.UnitTest/Probel.Lanceur.UnitTest.csproj +++ b/src/Tests/Probel.Lanceur.UnitTest/Probel.Lanceur.UnitTest.csproj @@ -25,6 +25,7 @@ DEBUG;TRACE prompt 4 + x64 pdbonly From 87c7cc2575eb7b77431d6f711065495f50ac4a2d Mon Sep 17 00:00:00 2001 From: jibedoubleve Date: Fri, 27 Mar 2020 13:08:22 +0100 Subject: [PATCH 4/5] Fix #62 - Can create alias names --- src/Probel.Lanceur.SQLiteDb/Services/SQLiteDatabaseService.cs | 4 ++-- src/Probel.Lanceur/ViewModels/EditAliasViewModel.cs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Probel.Lanceur.SQLiteDb/Services/SQLiteDatabaseService.cs b/src/Probel.Lanceur.SQLiteDb/Services/SQLiteDatabaseService.cs index 255850f..5ea6a23 100644 --- a/src/Probel.Lanceur.SQLiteDb/Services/SQLiteDatabaseService.cs +++ b/src/Probel.Lanceur.SQLiteDb/Services/SQLiteDatabaseService.cs @@ -268,14 +268,14 @@ public void Update(IEnumerable names) { using (var c = BuildConnection()) { - var sqlInsert = @"insert into alias_name (name, alias_id) values (@name, @aliasId)"; + var sqlInsert = @"insert into alias_name (name, id_alias) values (@name, @aliasId)"; var sqlUpdate = @"update alias_name set name = @name where id = @id"; foreach (var name in names) { if (name.Id == 0) { _log.Debug($"Insert new. id_alias: {name.IdAlias} - name: {name.Name} - id: {name.Id}"); - c.Execute(sqlInsert, new { name.Name, name.IdAlias }); + c.Execute(sqlInsert, new { name = name.Name, aliasId = name.IdAlias }); } else { diff --git a/src/Probel.Lanceur/ViewModels/EditAliasViewModel.cs b/src/Probel.Lanceur/ViewModels/EditAliasViewModel.cs index 9f05051..a9c2ce3 100644 --- a/src/Probel.Lanceur/ViewModels/EditAliasViewModel.cs +++ b/src/Probel.Lanceur/ViewModels/EditAliasViewModel.cs @@ -83,7 +83,7 @@ public void CreateAlias() } public async Task DeleteAliasAsync() - { + { if (await ParentVm.AskForDeletion(Alias.Name)) { _databaseService.Delete(Alias.AsEntity()); @@ -104,6 +104,8 @@ public void RefreshData(AliasModel model = null) public void UpdateAlias() { _databaseService.Update(Alias.AsEntity()); + + foreach (var name in Names) { name.IdAlias = Alias.Id; } _databaseService.Update(Names.AsEntity()); _userNotifyer.NotifyInfo("Alias updated!"); } From b68adaa7e42fb9a4bd97def5d1cc04ed15558b77 Mon Sep 17 00:00:00 2001 From: jibedoubleve Date: Fri, 27 Mar 2020 13:22:27 +0100 Subject: [PATCH 5/5] (maint) update cake build --- GitVersion.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GitVersion.yml b/GitVersion.yml index 8c49abd..f036ee9 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,5 +1,5 @@ assembly-versioning-scheme: MajorMinorPatchTag -next-version: 0.4.0 +next-version: 0.4.1 branches: master: mode: ContinuousDeployment