245 lines
7.6 KiB
C#
245 lines
7.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Sarand.Net.Standard.Base.App;
|
|
using Sarand.Net.Standard.Base.Core;
|
|
using Sarand.Net.Standard.Base.Utils;
|
|
|
|
namespace Sarand.Net.Standard.Base.Procs
|
|
{
|
|
//=======================================================================
|
|
public interface ISacsProcessNotifier
|
|
{
|
|
void OnStartProcess ();
|
|
void SetProgressInfo (List<String> progressInfo);
|
|
void OnEndProcess ();
|
|
}
|
|
|
|
//=======================================================================
|
|
public abstract class SacsProcess : SacsDisposable
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Process options and groups - for configuration of process to run.
|
|
// See Sarand.Win.Forms.Utility.SaForm_SelectOptions.
|
|
public class OptionData
|
|
{
|
|
public OptionData (TypeCodeDesc option)
|
|
{
|
|
Option = option;
|
|
}
|
|
public TypeCodeDesc Option { get; set; }
|
|
public String Notes { get; set; } = "";
|
|
public bool Selected { get; set; } = false;
|
|
}
|
|
public class GroupData
|
|
{
|
|
public GroupData (TypeCodeDesc optionGroup)
|
|
{
|
|
OptionGroup = optionGroup;
|
|
}
|
|
public TypeCodeDesc OptionGroup { get; set; }
|
|
public List<OptionData> Options { get; } = new List<OptionData>();
|
|
public bool ExclusiveOptions { get; set; } = false;
|
|
public bool Selected { get; set; } = false;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Configuration.
|
|
public enum ProcessType
|
|
{
|
|
Unknown = 0,
|
|
ImportData,
|
|
ExportData,
|
|
ImportExportData,
|
|
Other,
|
|
}
|
|
public class Config
|
|
{
|
|
protected Config ()
|
|
{
|
|
}
|
|
/// <summary>Identifies the type of process.</summary>
|
|
public ProcessType ProcessType { get; set; } = ProcessType.Unknown;
|
|
/// <summary>Is the process to be run in 'Test' mode.</summary>
|
|
public bool TestProcess{ get; set; } = SacsSystem.DebugMode;
|
|
/// <summary>Process imports data.</summary>
|
|
public bool Import { get { return ProcessType == ProcessType.ImportData || ProcessType == ProcessType.ImportExportData; } }
|
|
/// <summary>Process exports data.</summary>
|
|
public bool Export { get { return ProcessType == ProcessType.ExportData || ProcessType == ProcessType.ImportExportData; } }
|
|
/// <summary>Can the process be interrupted?</summary>
|
|
public bool AllowInterruption { get; set; } = true;
|
|
/// <summary>Confirm when interruption is requested.</summary>
|
|
public bool ConfirmInterruption { get; set; } = true;
|
|
/// <summary>Automated processes must not display desktop coponents - popup messages etc.</summary>
|
|
public bool Automated { get; set; } = false;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Data members.
|
|
private Config config;
|
|
private String processError = "";
|
|
|
|
//-------------------------------------------------------------------
|
|
// Construction.
|
|
protected SacsProcess (Config config)
|
|
{
|
|
this.config = config;
|
|
}
|
|
protected override void Dispose (bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Properties.
|
|
public bool DebugMode { get { return SacsSystem.DebugMode; } }
|
|
public ISacsProcessNotifier ProcessNotifier { get; set; } = null;
|
|
public bool Processing { get; protected set; } = false;
|
|
public bool ProcessEnded { get; protected set; } = false;
|
|
public DateTime StartedAt { get; private set; } = DateTime.MinValue;
|
|
public DateTime FinishedAt { get; private set; } = DateTime.MinValue;
|
|
public int ElapsedSecs
|
|
{
|
|
get
|
|
{
|
|
if (DateUtil.IsValid(StartedAt))
|
|
return (int)((DateUtil.IsValid(FinishedAt) ? FinishedAt : DateTime.Now) - StartedAt).TotalSeconds;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Properties.
|
|
/// <summary>Process caption.</summary>
|
|
public abstract String ProcessDescription { get; }
|
|
/// <summary>Process comments - to be displayed with process selection.</summary>
|
|
public virtual List<String> ProcessComments { get { return new List<String>(); } }
|
|
/// <summary>Processing statistics.</summary>
|
|
public virtual List<StringPair> ProcessingStatistics { get { return new List<StringPair>(); } }
|
|
|
|
//-------------------------------------------------------------------
|
|
// Run process inline.
|
|
public bool RunProcess ()
|
|
{
|
|
String fn = GetType().Name+".RunProcess";
|
|
if (ProcessNotifier == null)
|
|
throw new NotSupportedException("Process Notifier must be specified");
|
|
// Prepare process.
|
|
bool runProcess = false;
|
|
Reset();
|
|
Processing = true;
|
|
StartedAt = DateTime.Now;
|
|
try
|
|
{
|
|
// Notify start of process and log/ignore exceptions.
|
|
ProcessNotifier.OnStartProcess();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SaLogger.Error(fn + " OnStartProcess: " + GetProcessError() + exc.GetStackEntries(6).Concat("", "\n\tat "), true);
|
|
}
|
|
try
|
|
{
|
|
// Run process.
|
|
OnProcessStarting();
|
|
runProcess = Run();
|
|
OnProcessEnding();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SetProcessError(exc.GetType().Name + ": " + exc.Message);
|
|
SaLogger.Error(fn + " " + GetProcessError() + exc.GetStackEntries(6).Concat("", "\n\tat "), true);
|
|
}
|
|
// Processing completed.
|
|
FinishedAt = DateTime.Now;
|
|
Processing = false;
|
|
ProcessEnded = true;
|
|
try
|
|
{
|
|
// Notify end of process and log/ignore exceptions.
|
|
ProcessNotifier.OnEndProcess();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SaLogger.Error(fn + " OnEndProcess: " + GetProcessError() + exc.GetStackEntries(6).Concat("", "\n\tat "), true);
|
|
}
|
|
return runProcess;
|
|
}
|
|
protected abstract bool Run ();
|
|
protected virtual void OnProcessStarting () { }
|
|
protected virtual void OnProcessEnding () { }
|
|
|
|
//-------------------------------------------------------------------
|
|
// Process control.
|
|
public bool OK
|
|
{
|
|
get
|
|
{
|
|
if (HasProcessError()) return false;
|
|
if (isInterrupted) return false;
|
|
return true;
|
|
}
|
|
}
|
|
private void Reset ()
|
|
{
|
|
ClearProcessError();
|
|
isInterrupted = false;
|
|
ProcessEnded = false;
|
|
StartedAt = DateTime.MinValue;
|
|
FinishedAt = DateTime.MinValue;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Progress information.
|
|
protected void SetProgressInfo (String progressInfo)
|
|
{
|
|
SetProgressInfo(StringListUtil.CreateList(progressInfo));
|
|
}
|
|
protected void SetProgressInfo (List<String> progressInfo)
|
|
{
|
|
if (ProcessNotifier != null)
|
|
ProcessNotifier.SetProgressInfo(progressInfo);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Error handling.
|
|
public bool HasProcessError () { return !StringUtil.IsEmpty(processError); }
|
|
public String GetProcessError () { return StringUtil.EmptyOnNull(processError); }
|
|
public void ClearProcessError () { processError = ""; }
|
|
/// <summary>Record the processing error - always returns false.</summary>
|
|
public bool SetProcessError (String error)
|
|
{
|
|
processError = StringUtil.EmptyOnNull(error);
|
|
return false;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Interruption.
|
|
private bool isInterrupted = false;
|
|
public bool IsInterrupted
|
|
{
|
|
get { return isInterrupted; }
|
|
}
|
|
public bool Interrupt ()
|
|
{
|
|
if (!config.AllowInterruption)
|
|
{
|
|
SaLogger.Warn("SacsProcess.Interrupt() Interruptions not allowed in " + this.GetType().Name);
|
|
return false;
|
|
}
|
|
if (config.ConfirmInterruption && !IsInterruptionConfirmed()) return false;
|
|
isInterrupted = true;
|
|
return true;
|
|
}
|
|
protected virtual bool IsInterruptionConfirmed ()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
//=======================================================================
|
|
}
|