using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Tango.BL.Entities; using Tango.BL.Enumerations; using Tango.BL.ValueObjects; using Tango.Core; using Tango.Core.ExtensionMethods; namespace Tango.BL.ActionLogs { /// /// Represents the default implementation. /// /// /// public class DefaultActionLogManager : ExtendedObject, IActionLogManager { /// /// Gets or sets the action log comparer used to compare related objects. /// public IActionLogComparer ActionLogComparer { get; set; } /// /// Gets or sets a value indicating whether to perform the logging operations asynchronously. /// public bool IsAsync { get; set; } /// /// Initializes a new instance of the class. /// public DefaultActionLogManager() { IsAsync = true; ActionLogComparer = new DefaultActionLogComparer(); } /// /// Inserts a new action log (main entry point). /// /// The type. /// The user unique identifier. /// Name of the related object. /// The related object unique identifier. /// The diffference node tree. /// The message. public void InsertLog(ActionLogType type, string userGuid, string relatedObjectName, string relatedObjectGuid, ActionLogDifference difference, string message = null) { Task task = new Task(() => { using (ObservablesContext db = ObservablesContext.CreateDefault()) { try { ActionLog log = new ActionLog(); log.ActionType = type; log.LastUpdated = DateTime.UtcNow; log.UserGuid = userGuid; log.RelatedObjectName = relatedObjectName; log.RelatedObjectGuid = relatedObjectGuid; log.Message = message; log.DifferenceObject = difference; db.ActionLogs.Add(log); db.SaveChanges(); LogManager.Log($"Action log '{type}' inserted."); if (difference != null && difference.Children.Count > 0) { Debug.WriteLine($"Action log differences:\n{difference.ToJsonString()}"); } } catch (Exception ex) { LogManager.Log(ex, $"Error inserting action log '{type}'."); } } }); if (IsAsync) { task.Start(); } else { task.RunSynchronously(); } } /// /// Inserts a new action log (comparison entry). /// /// The type. /// The user unique identifier. /// Name of the related object. /// The related object before the change. /// The related object after the change. /// The message. public void InsertLog(ActionLogType type, string userGuid, string relatedObjectName, IActionLogComparable relatedObjectBefore, IActionLogComparable relatedObjectAfter, string message = null) { Task task = new Task(() => { ActionLogDifference diff = new ActionLogDifference(); bool insertWhenNoDifference = false; if (ActionLogComparer != null) { try { diff = ActionLogComparer.Compare(relatedObjectBefore, relatedObjectAfter).Result; } catch (Exception ex) { insertWhenNoDifference = true; LogManager.Log(ex, $"Error while comparing for action log '{type}'."); } if (diff.Children.Count > 0 || insertWhenNoDifference) { InsertLog(type, userGuid, relatedObjectName, GetRelatedObjectGuid(relatedObjectBefore, relatedObjectAfter), diff, message); } else { LogManager.Log($"Action log '{type}' was about to be inserted but skipped due to no differences."); } } else { Debug.WriteLine("No comparer defined for action log."); InsertLog(type, userGuid, relatedObjectName, GetRelatedObjectGuid(relatedObjectBefore, relatedObjectAfter), diff, message); } }); if (IsAsync) { task.Start(); } else { task.RunSynchronously(); } } /// /// Inserts a new action log (comparison entry). /// /// The type. /// The user. /// Name of the related object. /// The related object before the change. /// The related object after the change. /// The message. public void InsertLog(ActionLogType type, User user, string relatedObjectName, IActionLogComparable relatedObjectBefore, IActionLogComparable relatedObjectAfter, string message = null) { InsertLog(type, user.Guid, relatedObjectName, relatedObjectBefore, relatedObjectAfter, message); } /// /// Inserts a new action log (deletion/creation entry). /// /// The type. /// The user. /// Name of the related object. /// The related object. /// The message. /// if set to true will create a one way difference tree (use when the related object was deleted and needs to be monitored). public void InsertLog(ActionLogType type, User user, string relatedObjectName, IActionLogComparable relatedObject, string message = null, bool serializeRelatedObject = false) { if (serializeRelatedObject) { InsertLog(type, user.Guid, relatedObjectName, relatedObject, null, message); } else { InsertLog(type, user.Guid, relatedObjectName, relatedObject?.Guid, message); } } /// /// Inserts a new action log (creation entry). /// /// The type. /// The user unique identifier. /// Name of the related object. /// The related object unique identifier. /// The message. public void InsertLog(ActionLogType type, string userGuid, string relatedObjectName, string relatedObjectGuid, string message = null) { InsertLog(type, userGuid, relatedObjectName, relatedObjectGuid, null, message); } /// /// Inserts a new action log (nutral entry). /// /// The type. /// The user unique identifier. /// The message. public void InsertLog(ActionLogType type, string userGuid, string message = null) { InsertLog(type, userGuid, null, null, message); } /// /// Inserts a new action log (nutral entry). /// /// The type. /// The user. /// The message. public void InsertLog(ActionLogType type, User user, string message = null) { InsertLog(type, user.Guid, message); } /// /// Gets the related object unique identifier. /// /// The before. /// The after. /// private String GetRelatedObjectGuid(IActionLogComparable before, IActionLogComparable after) { if (before != null) { return before.Guid; } if (after != null) { return after.Guid; } return null; } } }