|
@@ -4,6 +4,7 @@ using InABox.Core.Postable;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
+using System.Reflection;
|
|
|
using System.Text;
|
|
|
|
|
|
namespace InABox.Core
|
|
@@ -12,7 +13,7 @@ namespace InABox.Core
|
|
|
public interface IPosterEngine<TPostable>
|
|
|
where TPostable : Entity, IPostable, IRemotable, IPersistent, new()
|
|
|
{
|
|
|
- bool Process(IEnumerable<TPostable> posts);
|
|
|
+ bool Process(IDataModel<TPostable> model);
|
|
|
}
|
|
|
|
|
|
public interface IPosterEngine<TPostable, TPoster, TSettings> : IPosterEngine<TPostable>
|
|
@@ -22,16 +23,11 @@ namespace InABox.Core
|
|
|
{
|
|
|
}
|
|
|
|
|
|
- public abstract class PosterEngine<TPostable, TPoster, TSettings> : IPosterEngine<TPostable, TPoster, TSettings>
|
|
|
- where TPostable : Entity, IPostable, IRemotable, IPersistent, new()
|
|
|
- where TPoster : IPoster<TPostable, TSettings>
|
|
|
- where TSettings : PosterSettings, new()
|
|
|
+ internal static class PosterEngineUtils
|
|
|
{
|
|
|
- protected static TPoster Poster = GetPoster();
|
|
|
-
|
|
|
private static Type[]? _posters;
|
|
|
|
|
|
- private static TPoster GetPoster()
|
|
|
+ public static Type GetPoster(Type TPoster)
|
|
|
{
|
|
|
_posters ??= CoreUtils.TypeList(
|
|
|
AppDomain.CurrentDomain.GetAssemblies(),
|
|
@@ -40,10 +36,35 @@ namespace InABox.Core
|
|
|
&& !x.IsGenericType
|
|
|
&& x.HasInterface(typeof(IPoster<,>))
|
|
|
).ToArray();
|
|
|
+ return _posters.Where(x => TPoster.IsAssignableFrom(x)).FirstOrDefault()
|
|
|
+ ?? throw new Exception($"No poster of type {TPoster}.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// A base class for all <see cref="IPosterEngine{TPostable}"/>. A concrete instance of this will be loaded by
|
|
|
+ /// <see cref="PosterUtils.Process{T}(IDataModel{T})"/>; a new instance is guaranteed to be created each time that method is called.
|
|
|
+ /// </summary>
|
|
|
+ /// <typeparam name="TPostable"></typeparam>
|
|
|
+ /// <typeparam name="TPoster"></typeparam>
|
|
|
+ /// <typeparam name="TSettings"></typeparam>
|
|
|
+ public abstract class PosterEngine<TPostable, TPoster, TSettings> : IPosterEngine<TPostable, TPoster, TSettings>
|
|
|
+ where TPostable : Entity, IPostable, IRemotable, IPersistent, new()
|
|
|
+ where TPoster : class, IPoster<TPostable, TSettings>
|
|
|
+ where TSettings : PosterSettings, new()
|
|
|
+ {
|
|
|
+ protected TPoster Poster;
|
|
|
|
|
|
- var type = _posters.Where(x => typeof(TPoster).IsAssignableFrom(x)).FirstOrDefault()
|
|
|
- ?? throw new Exception($"No poster of type {typeof(TPoster)}.");
|
|
|
- return (TPoster)Activator.CreateInstance(type);
|
|
|
+ public PosterEngine()
|
|
|
+ {
|
|
|
+ Poster = CreatePoster();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static readonly Type? PosterType = PosterEngineUtils.GetPoster(typeof(TPoster));
|
|
|
+
|
|
|
+ protected virtual TPoster CreatePoster()
|
|
|
+ {
|
|
|
+ return (Activator.CreateInstance(PosterType!) as TPoster)!;
|
|
|
}
|
|
|
|
|
|
protected static TSettings GetSettings()
|
|
@@ -66,45 +87,83 @@ namespace InABox.Core
|
|
|
return settings.ScriptEnabled ? settings.Script : null;
|
|
|
}
|
|
|
|
|
|
- protected abstract bool DoProcess(IEnumerable<TPostable> posts);
|
|
|
+ protected abstract bool DoProcess(IDataModel<TPostable> model);
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Process the <paramref name="model"/> before loading;
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="model"></param>
|
|
|
+ /// <returns><see langword="false"/> if the processing must be cancelled.</returns>
|
|
|
+ public abstract bool BeforePost(IDataModel<TPostable> model);
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Prior to saving the <typeparamref name="TPostable"/> entities, make any necessary changes to those entities.
|
|
|
+ /// This is only called if <see cref="Process(IDataModel{TPostable})"/> returned <see langword="true"/>.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="model"></param>
|
|
|
+ public abstract void AfterPost(IDataModel<TPostable> model);
|
|
|
|
|
|
- public bool Process(IEnumerable<TPostable> posts)
|
|
|
+ public bool Process(IDataModel<TPostable> model)
|
|
|
{
|
|
|
- var list = posts.AsList();
|
|
|
- if(list.Any(x => x.PostedStatus == PostedStatus.Posted))
|
|
|
+ if (!BeforePost(model))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ model.LoadModel();
|
|
|
+
|
|
|
+ var data = model.GetTable<TPostable>();
|
|
|
+
|
|
|
+ if (!data.Rows.Any())
|
|
|
+ {
|
|
|
+ throw new EmptyPostException();
|
|
|
+ }
|
|
|
+ if(data.Rows.Any(x => x.Get<TPostable, PostedStatus>(x => x.PostedStatus) == PostedStatus.Posted))
|
|
|
{
|
|
|
throw new RepostedException();
|
|
|
}
|
|
|
+
|
|
|
try
|
|
|
{
|
|
|
- var success = DoProcess(list);
|
|
|
+ var success = DoProcess(model);
|
|
|
if (success)
|
|
|
{
|
|
|
- foreach (var post in list)
|
|
|
+ AfterPost(model);
|
|
|
+ }
|
|
|
+
|
|
|
+ var entities = data.ToObjects<TPostable>().ToList();
|
|
|
+
|
|
|
+ if (success)
|
|
|
+ {
|
|
|
+ foreach (var post in entities)
|
|
|
{
|
|
|
post.Posted = DateTime.Now;
|
|
|
post.PostedStatus = PostedStatus.Posted;
|
|
|
+ post.PostedNote = "";
|
|
|
}
|
|
|
- new Client<TPostable>().Save(list, "Posted by user.");
|
|
|
+ new Client<TPostable>().Save(entities, "Posted by user.");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- foreach (var post in list)
|
|
|
+ foreach (var post in entities)
|
|
|
{
|
|
|
post.PostedStatus = PostedStatus.PostFailed;
|
|
|
+ post.PostedNote = "Post failed.";
|
|
|
}
|
|
|
- new Client<TPostable>().Save(list, "Post failed by user.");
|
|
|
+ new Client<TPostable>().Save(entities, "Post failed by user.");
|
|
|
}
|
|
|
return success;
|
|
|
}
|
|
|
catch(Exception e)
|
|
|
{
|
|
|
Logger.Send(LogType.Error, "", $"Post Failed: {CoreUtils.FormatException(e)}");
|
|
|
- foreach (var post in list)
|
|
|
+
|
|
|
+ var entities = data.ToObjects<TPostable>().ToList();
|
|
|
+ foreach (var post in entities)
|
|
|
{
|
|
|
post.PostedStatus = PostedStatus.PostFailed;
|
|
|
+ post.PostedNote = e.Message;
|
|
|
}
|
|
|
- new Client<TPostable>().Save(list, "Post failed by user.");
|
|
|
+ new Client<TPostable>().Save(entities, "Post failed by user.");
|
|
|
throw;
|
|
|
}
|
|
|
}
|