// Copyright (c) 2008, NTT DATA Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using TERASOLUNA.Fw.Common;
using TERASOLUNA.Fw.Common.Logging;
using TERASOLUNA.Fw.Common.Validation;

namespace TERASOLUNA.Fw.Client
{
    /// <summary>
    /// イベント処理機能を提供するクラスです。
    /// </summary>
    /// <remarks>
    /// イベントコントローラのプロパティで、実行する機能を設定します。
    /// </remarks>
    [DefaultEvent("ExecuteCompleted")]
    public class EventController : Component
    {
        /// <summary>
        /// <see cref="ILog"/> 実装クラスのインスタンスです。
        /// </summary>
        /// <remarks>
        /// ログ出力に利用します。
        /// </remarks>
        private static ILog _log = LogFactory.GetLogger(typeof(EventController));

        /// <summary>
        /// 通信相手に通知するリクエスト名のキー値です。
        /// </summary>
        /// <remarks>
        /// この定数の値は "RequestName" です。
        /// </remarks>
        public static readonly string REQUEST_NAME = "RequestName";

        /// <summary>
        /// データセット変換情報を識別するコンバートIDです。
        /// </summary>
        private string _convertId = null;

        /// <summary>
        /// 実行するビジネスロジックを識別するビジネスロジック名です。
        /// </summary>
        private string _blogicName = null;

        /// <summary>
        /// 通信相手に通知するリクエスト名です。
        /// </summary>
        private string _requestName = null;

        /// <summary>
        /// 入力値検証設定ファイルのパスです。
        /// </summary>
        private string _validationFilePath = null;

        /// <summary>
        /// 入力値検証ルールセットです。
        /// </summary>
        private string _ruleSet = null;

        /// <summary>
        /// 画面 <see cref="DataSet"/> です。
        /// </summary>
        private DataSet _viewData = null;

        /// <summary>
        /// ビジネスロジック入力 <see cref="DataSet"/> の型名です。
        /// </summary>
        private string _blogicParamTypeName = null;

        /// <summary>
        /// ビジネスロジック出力 <see cref="DataSet"/> の型名です。
        /// </summary>
        private string _blogicResultTypeName = null;

        /// <summary>
        /// エラー処理を委譲するエラー処理ハンドラです。
        /// </summary>
        private IErrorHandler _errorHandler = null;

        /// <summary>
        /// エラー発生箇所を表すキーを格納するリストです。
        /// </summary>
        private IList<string> _errorPaths = new List<string>();

        /// <summary>
        /// ビジネスロジックを実行するクラスです。
        /// </summary>
        private Coordinator _coordinator = null;

        /// <summary>
        /// 外部からアクセス可能なオブジェクトを保持します。
        /// </summary>
        private IDictionary<string, object> _items = new Dictionary<string, object>();

        /// <summary>
        /// <see cref="ReportCustomValidating"/> が呼び出されたときに発生します。
        /// </summary>
        [Category("動作"), Description("カスタムチェックを行うときに発生します。")]
        public event CustomValidatingEventHandler CustomValidating;

        /// <summary>
        /// <see cref="ReportValidationFailed"/> が呼び出されたときに発生します。
        /// </summary>
        [Category("動作"), Description("入力値検証エラー時に発生します。")]
        public event ValidationFailedEventHandler ValidationFailed;

        /// <summary>
        /// <see cref="ReportPreprocessed"/> が呼び出されたときに発生します。
        /// </summary>
        [Category("動作"), Description("前処理完了したときに発生します。")]
        public event PreprocessedEventHandler Preprocessed;

        /// <summary>
        /// <see cref="ReportPreprocessedFailed"/> が呼び出されたときに発生します。
        /// </summary>
        [Category("動作"), Description("前処理エラー時に発生します。")]
        public event PreprocessedFailedEventHandler PreprocessedFailed;

        /// <summary>
        /// <see cref="ReportBLogicFailed"/> が呼び出されたときに発生します。
        /// </summary>
        [Category("動作"), Description("ビジネスロジックが失敗したときに発生します。")]
        public event BLogicFailedEventHandler BLogicFailed;

        /// <summary>
        /// <see cref="ReportExecuteCompleted"/> が呼び出されたときに発生します。
        /// </summary>
        [Category("動作"), Description("非同期処理が成功したときに発生します。")]
        public event ExecuteCompletedEventHandler ExecuteCompleted;

        /// <summary>
        /// <see cref="ReportExecuteProgressChanged"/> が呼び出されたときに発生します。
        /// </summary>
        [Category("動作"), Description("バックグラウンド操作の進行状況を通知するときに発生します。")]
        public event ExecuteProgressChangedEventHandler ExecuteProgressChanged;

        /// <summary>
        /// <see cref="EventController"/> クラスの新しいインスタンスを初期化します。
        /// </summary>
        /// <remarks>
        /// デフォルトコンストラクタです。
        /// </remarks>
        public EventController()
        {
        }

        /// <summary>
        /// <see cref="EventController"/> クラスの新しいインスタンスを初期化します。
        /// </summary>
        /// <param name="container">
        /// 自動生成されたフォームのデザイナ変数。
        /// </param>
        public EventController(IContainer container)
        {
            if (container != null)
            {
                container.Add(this);
            }
        }

        /// <summary>
        /// コンバート ID を取得または設定します。
        /// </summary>
        /// <value>
        /// コンバート ID 。
        /// </value>
        [Category("イベント処理"), Description("データセット変換設定ファイルに定義されたコンバートIDを指定します。")]
        public string ConvertId
        {
            get
            {
                return _convertId;
            }
            set
            {
                _convertId = value;
            }
        }

        /// <summary>
        /// ビジネスロジック名を取得または設定します。
        /// </summary>
        /// <value>
        /// ビジネスロジック名。
        /// </value>
        [Category("イベント処理"), Description("ビジネスロジック設定ファイルに定義されたビジネスロジック名を指定します。")]
        public string BLogicName
        {
            get
            {
                return _blogicName;
            }
            set
            {
                _blogicName = value;
            }
        }

        /// <summary>
        /// 通信相手に通知するリクエスト名を取得または設定します。
        /// </summary>
        /// <value>
        /// 通信相手に通知するリクエスト名。
        /// </value>
        [Category("イベント処理"), Description("サーバで実行されるリクエスト処理の識別子を設定します。")]
        public string RequestName
        {
            get
            {
                return _requestName;
            }
            set
            {
                _requestName = value;
            }
        }

        /// <summary>
        /// 入力値検証設定ファイルパスを取得または設定します。
        /// </summary>
        /// <value>
        /// 入力値検証設定ファイルパス。
        /// </value>
        [Category("イベント処理"), Description("リソースまたはローカルにある入力値検証設定ファイルのパスを設定します。")]
        public string ValidationFilePath
        {
            get
            {
                return _validationFilePath;
            }
            set
            {
                _validationFilePath = value;
            }
        }

        /// <summary>
        /// 入力値検証ルールセットを取得または設定します。
        /// </summary>
        /// <value>
        /// 入力値検証ルールセット。
        /// </value>
        [Category("イベント処理"), Description("リソースまたはローカルにある入力値検証設定ファイルのルールセットを設定します。")]
        public string RuleSet
        {
            get
            {
                return _ruleSet;
            }
            set
            {
                _ruleSet = value;
            }
        }

        /// <summary>
        /// 画面 <see cref="DataSet"/> を取得または設定します。
        /// </summary>
        /// <value>
        /// 画面 <see cref="DataSet"/> 。
        /// </value>
        [Category("イベント処理"), Description("画面データセットを設定します。")]
        public DataSet ViewData
        {
            get
            {
                return _viewData;
            }
            set
            {
                _viewData = value;
            }
        }

        /// <summary>
        /// ビジネスロジック入力 <see cref="DataSet"/> の型名を取得または設定します。
        /// </summary>
        /// <value>
        /// ビジネスロジック入力 <see cref="DataSet"/> の型名。
        /// </value>
        [Category("イベント処理"), Description("ビジネスロジック入力データセットの完全修飾型名を設定します。")]
        public string BLogicParamTypeName
        {
            get
            {
                return _blogicParamTypeName;
            }
            set
            {
                _blogicParamTypeName = value;
            }
        }

        /// <summary>
        /// ビジネスロジック出力 <see cref="DataSet"/> の型名を取得または設定します。
        /// </summary>
        /// <value>
        /// ビジネスロジック出力 <see cref="DataSet"/> の型名。
        /// </value>
        [Category("イベント処理"), Description("ビジネスロジック出力データセットの完全修飾型名を設定します。")]
        public string BLogicResultTypeName
        {
            get
            {
                return _blogicResultTypeName;
            }
            set
            {
                _blogicResultTypeName = value;
            }
        }

        /// <summary>
        /// <see cref="Coordinator"/> が非同期処理を実行中かどうかを示す値を取得します。
        /// </summary>
        /// <value>
        /// <see cref="Coordinator"/> が非同期処理を実行中の場合は true 。
        /// それ以外の場合は false 。
        /// </value>
        [Browsable(false)]
        public bool IsBusy
        {
            get
            {
                return (_coordinator != null && _coordinator.IsBusy);
            }
        }

        /// <summary>
        /// エラー処理を委譲するエラー処理ハンドラを取得または設定します。
        /// </summary>
        /// <remarks>
        /// デザイナで、画面に 
        /// <see cref="TERASOLUNA.Fw.Client.EventController"/> コンポーネントを追加したとき、
        /// 画面の基底クラスが <see cref="IErrorHandler"/> を実装していれば、
        /// 自動的に基底クラスのインスタンスを設定します。
        /// </remarks>
        /// <value>
        /// エラー処理を委譲するエラー処理ハンドラ。
        /// </value>
        [Category("イベント処理"), Description("IErrorHandler実装クラスのインスタンスを設定します。")]
        public IErrorHandler ErrorHandler
        {
            get
            {
                return _errorHandler;
            }
            set
            {
                _errorHandler = value;
            }
        }

        /// <summary>
        /// エラー発生箇所を表すキーのリストを取得します。
        /// </summary>
        /// <value>
        /// エラー発生箇所を表すキーのリスト。
        /// </value>
        [Browsable(false)]
        public IList<string> ErrorPaths
        {
            get
            {
                return _errorPaths;
            }
        }

        /// <summary>
        /// 外部からアクセス可能なオブジェクトを取得または設定します。
        /// </summary>
        /// <value>
        /// 外部からアクセス可能なオブジェクト。
        /// </value>
        [Browsable(false)]
        public IDictionary<string, object> Items
        {
            get
            {
                return _items;
            }
        }

        /// <summary>
        /// ビジネスロジックを同期処理で実行し、
        /// <see cref="TERASOLUNA.Fw.Client.ExecutionResult"/>
        /// を返却します。
        /// </summary>
        /// <remarks>
        /// <para>
        /// <see cref="Coordinator"/>
        /// インスタンスを取得し、ビジネスロジックを同期処理で実行します。
        /// </para>
        /// </remarks>
        /// <returns>
        /// 実行結果を格納した <see cref="TERASOLUNA.Fw.Client.ExecutionResult"/> 。
        /// </returns>
        /// <exception cref="TerasolunaException">
        /// <see cref="Coordinator"/> 派生クラス、
        /// または、 <see cref="Coordinator"/> クラスのインスタンスを生成できません。
        /// </exception>
        public virtual ExecutionResult Execute()
        {
            _coordinator = Coordinator.CreateCoordinator();

            if (_log.IsDebugEnabled)
            {
                _log.Debug(Properties.Resources.D_BEGIN_EVENT_FUNCTION);
            }

            ExecutionResult executionResult = _coordinator.Execute(this);

            if (_log.IsDebugEnabled)
            {
                _log.Debug(Properties.Resources.D_END_EVENT_FUNCTION);
            }
            
            return executionResult;
        }

        /// <summary>
        /// ビジネスロジックを非同期処理で実行します。
        /// </summary>
        /// <remarks>
        /// <para>
        /// <see cref="Coordinator"/>
        /// インスタンスを取得し、ビジネスロジックを非同期処理で実行します。
        /// </para>
        /// <para>
        /// <see cref="IsBusy"/> が false の場合は、ビジネスロジックを非同期処理で実行します。
        /// </para>
        /// <para>
        /// <see cref="IsBusy"/> が true の場合は、例外をスローします。
        /// </para>
        /// </remarks>
        /// <exception cref="InvalidOperationException">
        /// すでに他の非同期処理が実行されています。
        /// </exception>
        /// <exception cref="TerasolunaException">
        /// <see cref="Coordinator"/> 派生クラス、
        /// または、<see cref="Coordinator"/> クラスのインスタンスを生成できません。
        /// </exception>
        public virtual void ExecuteAsync()
        {
            if (IsBusy)
            {
                InvalidOperationException exception = new InvalidOperationException(
                    Properties.Resources.E_BLOGIC_EXECUTEASYNC_OPERATED);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(exception.Message, exception);
                }
                throw exception;
            }

            _coordinator = Coordinator.CreateCoordinator();

            if (_log.IsDebugEnabled)
            {
                _log.Debug(Properties.Resources.D_BEGIN_EVENT_ASYNC_FUNCTION);
            }

            _coordinator.ExecuteAsync(this);

            if (_log.IsDebugEnabled)
            {
                _log.Debug(Properties.Resources.D_END_EVENT_ASYNC_FUNCTION);
            }

        }

        /// <summary>
        /// ビジネスロジックの非同期処理をキャンセルします。
        /// </summary>
        /// <remarks>
        /// <para>
        /// <see cref="Coordinator.ExecuteAsyncCancel"/> メソッドを呼び出し、
        /// ビジネスロジックの非同期処理をキャンセルします。
        /// </para>
        /// <para>
        /// <see cref="IsBusy"/> が false の場合、
        /// ビジネスロジックは実行されていないので例外をスローします。
        /// </para>
        /// <para>
        /// <see cref="IsBusy"/> が true の場合、
        /// <see cref="Coordinator.ExecuteAsyncCancel"/> メソッドを呼び出します。
        /// </para>
        /// <para>
        /// キャンセル後の完了イベントで渡される <see cref="TERASOLUNA.Fw.Client.ExecuteCompletedEventArgs"/> の
        /// ビジネスロジック処理結果が格納された <see cref="TERASOLUNA.Fw.Client.ExecutionResult"/> を参照すると
        /// <see cref="InvalidOperationException"/> がスローされます。
        /// </para>
        /// </remarks>
        /// <exception cref="InvalidOperationException">
        /// <see cref="Coordinator"/> で非同期処理は実行されていません。
        /// </exception>
        public virtual void ExecuteAsyncCancel()
        {
            if (!IsBusy)
            {
                InvalidOperationException exception = new InvalidOperationException(
                    Properties.Resources.E_BLOGIC_NOT_EXECUTEASYNC_OPERATED);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(exception.Message, exception);
                }
                throw exception;
            }

            if (_log.IsDebugEnabled)
            {
                _log.Debug(Properties.Resources.D_BEGIN_EVENT_ASYNC_CANCEL_FUNCTION);
            }

            _coordinator.ExecuteAsyncCancel();

            if(_log.IsDebugEnabled)
            {
                _log.Debug(Properties.Resources.D_END_EVENT_ASYNC_CANCEL_FUNCTION);
            }
        }

        /// <summary>
        /// イベントデータを格納する
        /// <see cref="CustomValidatingEventArgs"/>
        /// を生成し、カスタムチェックイベント通知を行うメソッドを呼び出します。
        /// </summary>
        /// <para>
        /// 画面 <see cref="DataSet"/> と
        /// 検証結果のエラーリストを保持する <see cref="ValidationResult"/> を受け取って、
        /// イベントデータを格納する
        /// <see cref="CustomValidatingEventArgs"/> を生成し、
        /// カスタムチェックイベント通知を行うメソッドを呼び出します。
        /// </para>
        /// <param name="validationResult">
        /// 検証結果のエラーリストを保持する <see cref="ValidationResult"/> 。
        /// </param>
        public virtual void ReportCustomValidating(ValidationResult validationResult)
        {
            CustomValidatingEventArgs args = 
                new CustomValidatingEventArgs(validationResult);
            OnCustomValidating(args);
        }

        /// <summary>
        /// イベントデータを格納する
        /// <see cref="ValidationFailedEventArgs"/> を生成し、
        /// 入力値検証エラーイベント通知を行うメソッドを呼び出します。
        /// </summary>
        /// <para>
        /// 画面 <see cref="DataSet"/> と
        /// <see cref="ExecutionResult"/> を受け取って、
        /// イベントデータを格納する
        /// <see cref="ValidationFailedEventArgs"/> を生成し、
        /// 入力値検証エラーイベント通知を行うメソッドを呼び出します。
        /// </para>
        /// <param name="executionResult">
        /// 実行結果を格納する <see cref="ExecutionResult"/> 。
        /// </param>
        public virtual void ReportValidationFailed(ExecutionResult executionResult)
        {
            ValidationFailedEventArgs args =
                new ValidationFailedEventArgs(executionResult);
            OnValidationFailed(args);
        }

        /// <summary>
        /// イベントデータを格納する
        /// <see cref="PreprocessedEventArgs"/> を生成し、
        /// 前処理完了イベント通知を行うメソッドを呼び出します。
        /// </summary>
        /// <remarks>
        /// <para>
        /// ビジネスロジック入力 <see cref="DataSet"/> と
        /// <see cref="ExecutionResult"/>
        /// を受け取ってイベントデータを格納する
        /// <see cref="PreprocessedEventArgs"/>
        /// を生成し、前処理完了イベント通知を行うメソッドを呼び出します。
        /// </para>
        /// </remarks>
        /// <param name="executionResult">
        /// 実行結果を格納する <see cref="ExecutionResult"/> 。
        /// </param>
        /// <param name="blogicParamData">
        /// ビジネスロジック入力 <see cref="DataSet"/> 。
        /// </param>
        public virtual void ReportPreprocessed(
            ExecutionResult executionResult, DataSet blogicParamData)
        {
            PreprocessedEventArgs args =
                new PreprocessedEventArgs(executionResult, blogicParamData);
            OnPreprocessed(args);
        }

        /// <summary>
        /// イベントデータを格納する
        /// <see cref="PreprocessedFailedEventArgs"/>
        /// を生成し、前処理エラーイベント通知を行うメソッドを呼び出します。
        /// </summary>
        /// <para>
        /// ビジネスロジック入力 <see cref="DataSet"/> と
        /// <see cref="ExecutionResult"/> を受け取って、
        /// イベントデータを格納する<see cref="PreprocessedFailedEventArgs"/> を生成し、
        /// 入力値検証エラーイベント通知を行うメソッドを呼び出します。
        /// </para>
        /// <param name="executionResult">
        /// 実行結果を格納する <see cref="ExecutionResult"/> 。
        /// </param>
        /// <param name="blogicParamData">
        /// ビジネスロジック入力 <see cref="DataSet"/> 。
        /// </param>
        public virtual void ReportPreprocessedFailed(
            ExecutionResult executionResult, DataSet blogicParamData)
        {
            PreprocessedFailedEventArgs args =
                new PreprocessedFailedEventArgs(executionResult, blogicParamData);
            OnPreprocessedFailed(args);
        }

        /// <summary>
        /// イベントデータを格納する
        /// <see cref="BLogicFailedEventArgs"/>
        /// を生成し、ビジネスロジック失敗イベント通知を行うメソッドを呼び出します。
        /// </summary>
        /// <para>
        /// <see cref="ExecutionResult"/> を受け取って、
        /// イベントデータを格納する <see cref="BLogicFailedEventArgs"/> を生成し、
        /// 入力値検証エラーイベント通知を行うメソッドを呼び出します。
        /// </para>
        /// <param name="executionResult">
        /// 実行結果を格納する <see cref="ExecutionResult"/> 。
        /// </param>
        public virtual void ReportBLogicFailed(ExecutionResult executionResult)
        {
            BLogicFailedEventArgs args = new BLogicFailedEventArgs(executionResult);
            OnBLogicFailed(args);
        }

        /// <summary>
        /// イベントデータを格納する
        /// <see cref="ExecuteCompletedEventArgs"/>
        /// を生成し、非同期処理完了イベント通知を行うメソッドを呼び出します。
        /// </summary>
        /// <remarks>
        /// <para>
        /// <see cref="ExecutionResult"/> 、
        /// 例外、キャンセル情報を受け取ってイベントデータを格納する
        /// <see cref="ExecuteCompletedEventArgs"/>
        /// を生成し、イベント処理完了イベント通知を行うメソッドを呼び出します。
        /// </para>
        /// </remarks>
        /// <param name="executionResult">実行結果などを格納する <see cref="ExecutionResult"/> 。</param>
        /// <param name="error"><see cref="Coordinator"/> 内で発生した <see cref="Exception"/> 。</param>
        /// <param name="cancelled">キャンセル情報。</param>
        public virtual void ReportExecuteCompleted(
            ExecutionResult executionResult,Exception error, bool cancelled)
        {
            ExecuteCompletedEventArgs args = 
                new ExecuteCompletedEventArgs(executionResult, error, cancelled);
            OnExecuteCompleted(args);
        }

        /// <summary>
        /// イベントデータを格納する
        /// <see cref="ExecuteProgressChangedEventArgs"/>
        /// を生成し、進行状況イベント通知を行うメソッドを呼び出します。
        /// </summary>
        /// <remarks>
        /// <para>
        /// 進行状況の割合とイベントハンドラへ渡すコレクションを受け取って
        /// イベントデータを格納する
        /// <see cref="ExecuteProgressChangedEventArgs"/> を生成し
        /// 進行状況イベント通知を行うメソッドを呼び出します。
        /// </para>
        /// </remarks>
        /// <param name="progressPercentage">進行状況の割合。</param>
        /// <param name="items">イベントハンドラへ渡すコレクション。</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="items"/> が null 参照です。
        /// </exception>
        public virtual void ReportExecuteProgressChanged(int progressPercentage, IDictionary items)
        {
            if (items == null)
            {
                ArgumentNullException exception = new ArgumentNullException("items");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(Properties.Resources.E_NULL_ARGUMENT, "items"), exception);
                }
                throw exception;
            }

            ExecuteProgressChangedEventArgs args = new ExecuteProgressChangedEventArgs(progressPercentage);

            foreach (DictionaryEntry item in items)
            {
                args.Items[item.Key] = item.Value;
            }

            OnExecuteProgressChanged(args);

            foreach (DictionaryEntry item in args.Items)
            {
                items[item.Key] = item.Value;
            }
        }

        /// <summary>
        /// カスタムチェックイベントに登録されたイベントハンドラに対して通知をします。
        /// </summary>
        /// <param name="e">
        /// イベントデータを格納している <see cref="CustomValidatingEventArgs"/> 。
        /// </param>
        protected virtual void OnCustomValidating(CustomValidatingEventArgs e)
        {
            if (CustomValidating != null)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_BEGIN_EVENT, "CustomValidating"));
                }

                CustomValidating(this, e);

                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_END_EVENT, "CustomValidating"));
                }
            }
        }

        /// <summary>
        /// 入力値検証エラーイベントに登録されたイベントハンドラに対して通知をします。
        /// </summary>
        /// <param name="e">
        /// イベントデータを格納している <see cref="ValidationFailedEventArgs"/> 。
        /// </param>
        protected virtual void OnValidationFailed(ValidationFailedEventArgs e)
        {
            if (ValidationFailed != null)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_BEGIN_EVENT, "ValidationFailed"));
                }

                ValidationFailed(this, e);

                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_END_EVENT, "ValidationFailed"));
                }
            }
        }

        /// <summary>
        /// 前処理完了イベントに登録されたイベントハンドラに対して通知をします。
        /// </summary>
        /// <param name="e">
        /// イベントデータを格納している <see cref="PreprocessedEventArgs"/> 。
        /// </param>
        protected virtual void OnPreprocessed(PreprocessedEventArgs e)
        {
            if (Preprocessed != null)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_BEGIN_EVENT, "Preprocessed"));
                }

                Preprocessed(this, e);

                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_END_EVENT, "Preprocessed"));
                }
            }
        }

        /// <summary>
        /// 前処理エラーイベントに登録されたイベントハンドラに対して通知をします。
        /// </summary>
        /// <param name="e">
        /// イベントデータを格納している <see cref="PreprocessedFailedEventArgs"/> 。
        /// </param>
        protected virtual void OnPreprocessedFailed(PreprocessedFailedEventArgs e)
        {
            if (PreprocessedFailed != null)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_BEGIN_EVENT, "PreprocessedFailed"));
                }

                PreprocessedFailed(this, e);

                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_END_EVENT, "PreprocessedFailed"));
                }
            }
        }

        /// <summary>
        /// ビジネスロジックエラーイベントに登録されたイベントハンドラに対して通知をします。
        /// </summary>
        /// <param name="e">
        /// イベントデータを格納している <see cref="BLogicFailedEventArgs"/> 。
        /// </param>
        protected virtual void OnBLogicFailed(BLogicFailedEventArgs e)
        {
            if (BLogicFailed != null)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_BEGIN_EVENT, "BLogicFailed"));
                }

                BLogicFailed(this, e);

                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_END_EVENT, "BLogicFailed"));
                }
            }
        }

        /// <summary>
        /// 非同期処理完了イベントに登録されたイベントハンドラに対して通知をします。
        /// </summary>
        /// <param name="e">
        /// イベントデータを格納している <see cref="ExecuteCompletedEventArgs"/> 。
        /// </param>
        protected virtual void OnExecuteCompleted(ExecuteCompletedEventArgs e)
        {
            if (ExecuteCompleted != null)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_BEGIN_EVENT, "ExecuteCompleted"));
                }

                ExecuteCompleted(this, e);

                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_END_EVENT, "ExecuteCompleted"));
                }
            }
        }

        /// <summary>
        /// 進行状況イベントに登録されたイベントハンドラに対して通知をします。
        /// </summary>
        /// <param name="e">
        /// イベントデータを格納している <see cref="ExecuteProgressChangedEventArgs"/> 。
        /// </param>
        protected virtual void OnExecuteProgressChanged(ExecuteProgressChangedEventArgs e)
        {
            if (ExecuteProgressChanged != null)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_BEGIN_EVENT, "ExecuteProgressChanged"));
                }

                ExecuteProgressChanged(this, e);

                if (_log.IsDebugEnabled)
                {
                    _log.Debug(string.Format(Properties.Resources.D_END_EVENT, "ExecuteProgressChanged"));
                }
            }
        }
    }

    /// <summary>
    /// カスタムチェックイベントハンドラのデリゲートです。
    /// </summary>
    /// <param name="sender">イベントのソース。</param>
    /// <param name="e">イベントデータを格納している <see cref="CustomValidatingEventArgs"/> 。</param>
    public delegate void CustomValidatingEventHandler(object sender, CustomValidatingEventArgs e);

    /// <summary>
    /// 入力値検証エラーイベントハンドラのデリゲートです。
    /// </summary>
    /// <param name="sender">イベントのソース。</param>
    /// <param name="e">イベントデータを格納している <see cref="ValidationFailedEventArgs"/> 。</param>
    public delegate void ValidationFailedEventHandler(object sender, ValidationFailedEventArgs e);

    /// <summary>
    /// 前処理完了イベントハンドラのデリゲートです。
    /// </summary>
    /// <param name="sender">イベントのソース。</param>
    /// <param name="e">イベントデータを格納している <see cref="PreprocessedEventArgs"/> 。</param>
    public delegate void PreprocessedEventHandler(object sender, PreprocessedEventArgs e);

    /// <summary>
    /// 前処理エラーイベントのデリゲートです。
    /// </summary>
    /// <param name="sender">イベントのソース。</param>
    /// <param name="e">イベントデータを格納している <see cref="PreprocessedFailedEventArgs"/> 。</param>
    public delegate void PreprocessedFailedEventHandler(object sender, PreprocessedFailedEventArgs e);

    /// <summary>
    /// ビジネスロジックエラーイベントのデリゲートです。
    /// </summary>
    /// <param name="sender">イベントのソース。</param>
    /// <param name="e">イベントデータを格納している <see cref="BLogicFailedEventArgs"/> 。</param>
    public delegate void BLogicFailedEventHandler(object sender, BLogicFailedEventArgs e);

    /// <summary>
    /// 非同期処理正常イベントのデリゲートです。
    /// </summary>
    /// <param name="sender">イベントのソース。</param>
    /// <param name="e">イベントデータを格納している <see cref="ExecuteCompletedEventArgs"/> 。</param>
    public delegate void ExecuteCompletedEventHandler(object sender, ExecuteCompletedEventArgs e);

    /// <summary>
    /// 進行状況イベントハンドラのデリゲートです。
    /// </summary>
    /// <param name="sender">イベントのソース。</param>
    /// <param name="e">イベントデータを格納している <see cref="ExecuteProgressChangedEventArgs"/> 。</param>
    public delegate void ExecuteProgressChangedEventHandler(object sender, ExecuteProgressChangedEventArgs e);
}
