using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using JD.Collections.Extensions;
using JD.Kernel.Classes;
using JD.Kernel.StaticHelpers;
using JD.Kernel.Structs;
namespace JD.LogService
{
///
/// A is used to aggregate message, warnings and errors in a list.
///
public class LoggingContext : ILogger
{
#region Inner Types
///
/// An add-only list.
///
private class List : Collection where T : LogEvent
{
#region Variables
private readonly LoggingContext m_parent;
#endregion
#region Constructor
public List(LoggingContext parent)
{
m_parent = parent;
}
#endregion
#region Methods
///
/// The function invoked when the user inserts an item in the list, it will be handled by our parent.
///
///
///
protected override void InsertItem(int index, T item)
{
m_parent.Log(item);
}
protected override void ClearItems()
{
throw new InvalidOperationException("Can only add items to the list.");
}
protected override void RemoveItem(int index)
{
throw new InvalidOperationException("Can only add items to the list.");
}
protected override void SetItem(int index, T item)
{
throw new InvalidOperationException("Can only add items to the list.");
}
///
/// Function invoked when the parent inserts an item in the list, it simply insert the item.
///
public void AddInternal(T item)
{
ICollection baseCollection = this;
lock (baseCollection.SyncRoot)
{
base.InsertItem(Count, item);
}
}
#endregion
}
///
/// Accompanies the BeforeEventLogged event.
///
public class BeforeEventLoggedEventArgs : CancelEventArgs
{
#region Variables
private LogEvent m_event;
#endregion
#region Constructors
///
/// Ctor.
///
///
public BeforeEventLoggedEventArgs(LogEvent @event)
{
m_event = @event;
}
#endregion
#region Properties
///
/// The event beeing logged (can be swapped).
///
public LogEvent Event
{
get { return m_event; }
set
{
Throw.IfNull(value, "value");
m_event = value;
}
}
#endregion
}
#endregion
#region Variables
private readonly List m_log;
private readonly List m_errors;
private readonly List m_warnings;
private readonly List m_messages;
#endregion
#region Constructor
///
/// Constructor.
///
public LoggingContext()
{
m_errors = new List(this);
m_warnings = new List(this);
m_messages = new List(this);
m_log = new List(this);
}
#endregion
#region Properties
///
/// Accesses the collection of errors.
///
public IList Errors
{
get { return m_errors; }
}
///
/// Accesses the collection of warnings (non critical errors).
///
public IList Warnings
{
get { return m_warnings; }
}
///
/// Accesses the collection of messages.
///
public IList Messages
{
get { return m_messages; }
}
///
/// Accesses the entire collection of all the log events.
///
public IList FullLog
{
get { return m_log; }
}
#endregion
#region Events
///
/// Triggered when an error is added in .
///
public event EventHandler> ErrorAdded;
///
/// Triggers the event.
///
/// Event Args.
protected virtual void OnErrorAdded(ItemEventArgs e)
{
ErrorAdded?.Invoke(this, e);
}
///
/// Triggered when a warning is added in .
///
public event EventHandler> WarningAdded;
///
/// Triggers the event.
///
/// Event Args.
protected virtual void OnWarningAdded(ItemEventArgs e)
{
WarningAdded?.Invoke(this, e);
}
///
/// Triggered when a message is added in .
///
public event EventHandler> MessageAdded;
///
/// Triggers the event.
///
/// Event Args.
protected virtual void OnMessageAdded(ItemEventArgs e)
{
MessageAdded?.Invoke(this, e);
}
///
/// Triggered when a item is logged in .
///
public event EventHandler> EventLogged;
///
/// Triggers the event.
///
/// Event Args.
protected virtual void OnEventLogged(ItemEventArgs e)
{
EventLogged?.Invoke(this, e);
}
///
/// Triggered before an item is logged in .
///
public event EventHandler BeforeEventLogged;
///
/// Triggers the event.
///
/// Event Args.
protected virtual void OnBeforeEventLogged(BeforeEventLoggedEventArgs e)
{
BeforeEventLogged?.Invoke(this, e);
}
#endregion
#region ILogger Members
///
/// Log an event in the logger.
///
///
/// The event will be dispatched in the correct collection.
public void Log(LogEvent @event)
{
Throw.IfNull(@event, "event");
BeforeEventLoggedEventArgs args = new BeforeEventLoggedEventArgs(@event);
OnBeforeEventLogged(args);
if (args.Cancel)
{
return;
}
@event = args.Event;
m_log.AddInternal(@event);
OnEventLogged(new ItemEventArgs(@event));
switch (@event.Category)
{
case LogCategory.Message:
Message message = @event as Message;
Trace.Assert(message != null);
m_messages.AddInternal(message);
OnMessageAdded(new ItemEventArgs(message));
break;
case LogCategory.Warning:
Error warning = @event as Error;
Trace.Assert(warning != null);
m_warnings.AddInternal(warning);
OnWarningAdded(new ItemEventArgs(warning));
break;
case LogCategory.Error:
Error error = @event as Error;
Trace.Assert(error != null);
m_errors.AddInternal(error);
OnErrorAdded(new ItemEventArgs(error));
break;
}
}
#endregion
#region Static methods
///
/// Creates a logging context that redirects all its inputs to the given logger.
///
/// Logger to redirect to.
///
public static LoggingContext FromLogger(ILogger logger)
{
LoggingContext context = new LoggingContext();
context.EventLogged += delegate(object sender, ItemEventArgs e)
{
logger.Log(e.Item);
};
return context;
}
///
/// Creates a logger that logs to the console.
///
public static LoggingContext CreateConsoleLogger()
{
LoggingContext result = new LoggingContext();
ILogger consoleLogger = Logger.CreateConsoleLogger();
result.EventLogged += (sender, e) => consoleLogger.Log(e.Item);
return result;
}
#endregion
#region Logging Helper
///
/// Log an event in the logger.
///
///
///
///
[Obsolete("Use the extension methods on ILogger instead (LogError, LogWarning, LogMessage).")] // 2011.01
public LogEvent Log(LogCategory category, string message, params object[] args)
{
LogEvent @event = LogEvent.Formatted(category, message, args);
Log(@event);
return @event;
}
///
/// Log an event in the logger.
///
///
///
///
///
[Obsolete("Use the extension methods on ILogger instead (LogError, LogWarning, LogMessage).")] // 2011.01
public LogEvent Log(LogCategory category, FileLocation origin, string message, params object[] args)
{
LogEvent @event = LogEvent.Formatted(category, origin, message, args);
Log(@event);
return @event;
}
///
/// Logs the content of the given logging context into this one.
///
///
public void Log(LoggingContext log)
{
log.FullLog.ForEach(Log);
}
#endregion
}
}