// 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 Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

namespace TERASOLUNA.Fw.Common.Validation.Validators
{
    /// <summary>
    /// 数値型指定範囲チェックを行う <see cref="Microsoft.Practices.EnterpriseLibrary.Validation.Validator"/>
    /// の基底クラスです。このクラスは抽象クラスです。
    /// </summary>
    /// <typeparam name="T">範囲チェックを行う数値型。</typeparam>
    /// <remarks>
    /// <para>
    /// 検証対象が型パラメータで渡された型である、または渡された型に変換可能な string の場合、
    /// 範囲チェックを行います。 null または空文字列については検証を行いません。
    /// </para>
    /// <para>
    /// 本クラスは派生クラスによって機能が実装されます。独自に派生クラスを作成する場合、
    /// 検証対象の型を <see cref="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationElementTypeAttribute"/> 属性に指定します。
    /// また、検証対象とする型を型パラメータとして渡すようにしてください。その際、
    /// 属性に指定する型パラメータと同じ型を指定する必要があります。
    /// </para>
    /// <para>
    /// 検索条件によって異なる検証エラー時に利用するデフォルトメッセージテンプレートを定義します。
    /// </para>
    /// </remarks>
    public abstract class NumberRangeValidator<T> : TypeRangeValidator<T> where T : IComparable
    {
        private static readonly string PATTERN_FORMAT = "{0}_{1}";

        /// <summary>
        /// コンストラクタ。派生クラスから呼び出されます。
        /// </summary>
        /// <param name="lowerBound">型パラメータで与えられた型の最小値。</param>
        /// <param name="lowerBoundType">範囲における最小値の扱いを示す <see cref="RangeBoundaryType"/> 列挙の値。
        /// 指定しない場合、Ignoreが使用されます。</param>
        /// <param name="upperBound">型パラメータで与えられた型の最大値。</param>
        /// <param name="upperBoundType">範囲における最大値の扱いを示す <see cref="RangeBoundaryType"/> 列挙の値。
        /// 指定しない場合、Inclusiveが利用されます。</param>
        /// <param name="messageTemplate">検証失敗の際、メッセージを生成するために利用するテンプレート文字列。
        /// 検証に利用するパラメータがプレースホルダに渡されます。
        /// パラメータとそのプレースホルダ番号は以下の通りです。
        /// <list type="table">
        /// <listheader>
        /// <term>プレースホルダ</term>
        /// <description>内容</description>
        /// </listheader>
        /// <item>
        /// <term>{0}</term>
        /// <description>検証対象文字列</description>
        /// </item>
        /// <item>
        /// <term>{1}</term>
        /// <description>key(プロパティ・メソッド名)</description>
        /// </item>
        /// <item>
        /// <term>{2}</term>
        /// <description>Tag文字列</description>
        /// </item>
        /// <item>
        /// <term>{3}</term>
        /// <description>LowerBound</description>
        /// </item>
        /// <item>
        /// <term>{4}</term>
        /// <description>LowerBoundType</description>
        /// </item>
        /// <item>
        /// <term>{5}</term>
        /// <description>UpperBound</description>
        /// </item>
        /// <item>
        /// <term>{6}</term>
        /// <description>UpperBoundType</description>
        /// </item>
        /// </list>
        /// </param>
        /// <param name="negated">検証条件の反転を示すフラグ。
        /// 反転した条件で検証を実施する場合には true を指定します。</param>
        protected NumberRangeValidator(T lowerBound,
                                 RangeBoundaryType lowerBoundType,
                                 T upperBound,
                                 RangeBoundaryType upperBoundType,
                                 string messageTemplate,
                                 bool negated)
            : base(lowerBound, lowerBoundType, upperBound, upperBoundType, messageTemplate, negated)
        {
        }

        /// <summary>
        /// 数値型に型指定された範囲チェック <see cref="Microsoft.Practices.EnterpriseLibrary.Validation.Validator"/> で利用する、
        /// <seealso cref="ValueValidator.Negated"/> が true である場合に使用されるデフォルトのメッセージテンプレートを取得します。
        /// </summary>
        /// <value>検証ルール反転時のデフォルトメッセージテンプレート文字列。</value>
        protected override string DefaultNegatedMessageTemplate
        {
            get
            {
                string pattern = string.Format(PATTERN_FORMAT, LowerBoundType.ToString(), UpperBoundType.ToString());
                string result = null;
                switch (pattern)
                {
                    case IGNORE_INCLUSIVE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NEGATED_IG_IN_MESSAGETEMPLATE;
                        break;
                    case IGNORE_EXCLUSIVE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NEGATED_IG_EX_MESSAGETEMPLATE;
                        break;
                    case INCLUSIVE_IGNORE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NEGATED_IN_IG_MESSAGETEMPLATE;
                        break;
                    case INCLUSIVE_INCLUSIVE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NEGATED_IN_IN_MESSAGETEMPLATE;
                        break;
                    case INCLUSIVE_EXCLUSIVE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NEGATED_IN_EX_MESSAGETEMPLATE;
                        break;
                    case EXCLUSIVE_IGNORE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NEGATED_EX_IG_MESSAGETEMPLATE;
                        break;
                    case EXCLUSIVE_INCLUSIVE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NEGATED_EX_IN_MESSAGETEMPLATE;
                        break;
                    case EXCLUSIVE_EXCLUSIVE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NEGATED_EX_EX_MESSAGETEMPLATE;
                        break;
                    default:
                        result = base.DefaultNegatedMessageTemplate;
                        break;
                }
                return result;
            }
        }

        /// <summary>
        /// 数値型に型指定された範囲チェック <see cref="Microsoft.Practices.EnterpriseLibrary.Validation.Validator"/> で利用する、
        /// <seealso cref="ValueValidator.Negated"/> が false である場合に使用されるデフォルトのメッセージテンプレートを取得します。
        /// </summary>
        /// <value>デフォルトメッセージテンプレート文字列。</value>
        protected override string DefaultNonNegatedMessageTemplate
        {
            get
            {
                string pattern = string.Format(PATTERN_FORMAT, LowerBoundType.ToString(), UpperBoundType.ToString());
                string result = null;
                switch (pattern)
                {
                    case IGNORE_INCLUSIVE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NONNEGATED_IG_IN_MESSAGETEMPLATE;
                        break;
                    case IGNORE_EXCLUSIVE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NONNEGATED_IG_EX_MESSAGETEMPLATE;
                        break;
                    case INCLUSIVE_IGNORE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NONNEGATED_IN_IG_MESSAGETEMPLATE;
                        break;
                    case INCLUSIVE_INCLUSIVE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NONNEGATED_IN_IN_MESSAGETEMPLATE;
                        break;
                    case INCLUSIVE_EXCLUSIVE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NONNEGATED_IN_EX_MESSAGETEMPLATE;
                        break;
                    case EXCLUSIVE_IGNORE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NONNEGATED_EX_IG_MESSAGETEMPLATE;
                        break;
                    case EXCLUSIVE_INCLUSIVE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NONNEGATED_EX_IN_MESSAGETEMPLATE;
                        break;
                    case EXCLUSIVE_EXCLUSIVE:
                        result = Properties.Resources.NUMBER_RANGE_VALIDATOR_NONNEGATED_EX_EX_MESSAGETEMPLATE;
                        break;
                    default:
                        result = base.DefaultNonNegatedMessageTemplate;
                        break;
                }
                return result;
            }
        }
    }
}
