/*
 * Copyright 2006 Takahiro Nakamura.
 *
 * 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.
 */
package woolpack.visitor.impl;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

import woolpack.locale.BranchByLocaleValidator;
import woolpack.text.FormatFactory;
import woolpack.utils.MapBuilder;
import woolpack.utils.Switchable;
import woolpack.validator.BranchByIdValidator;
import woolpack.validator.BranchByNameIfExistsValidator;
import woolpack.validator.BranchByNameValidator;
import woolpack.validator.CountValidator;
import woolpack.validator.DefaultValueValidator;
import woolpack.validator.DelegationValidator;
import woolpack.validator.DumpValidator;
import woolpack.validator.EqualsValidator;
import woolpack.validator.FormatValidator;
import woolpack.validator.IfNotValidator;
import woolpack.validator.IfValidator;
import woolpack.validator.MaxLengthValidator;
import woolpack.validator.MaxValidator;
import woolpack.validator.MessageValidator;
import woolpack.validator.MinLengthValidator;
import woolpack.validator.MinValidator;
import woolpack.validator.NotValidator;
import woolpack.validator.ParseValidator;
import woolpack.validator.RegExpIdValidator;
import woolpack.validator.RegExpValidator;
import woolpack.validator.RetainNamesValidator;
import woolpack.validator.SerialValidator;
import woolpack.validator.TmpIndexValidator;
import woolpack.validator.TmpKeyValidator;
import woolpack.validator.ValidNamesValidator;
import woolpack.validator.ValidValuesValidator;
import woolpack.validator.ValidatorConstants;
import woolpack.validator.ValueLoopValidator;
import woolpack.visitor.Acceptable;
import woolpack.visitor.DomVisitorConstants;
import woolpack.visitor.HtmlVisitorConstants;
import woolpack.visitor.Visitor;
import woolpack.visitor.VisitorConstants;

/**
 * {@link woolpack.validator.ValidatorExpression}の
 * コンストラクタツリーを日本語 HTML ドキュメントに変換するための定数の集まり。
 * 
 * @author nakamura
 * 
 */
public final class DocValidatorConstants {

	/**
	 * {@link wookpack.validator}パッケージで定義されているクラスに関する コンストラクタツリーを日本語 HTML
	 * ドキュメントに変換するために使用する{@link Map}。
	 */
	public static final Map<Object, Acceptable> BASE = Collections
			.unmodifiableMap(MapBuilder.get(
					new LinkedHashMap<Object, Acceptable>()).put(
					ValidatorConstants.TRUE,
					VisitorConstants.visitAcceptable("なにもしない。")).put(
					ValidatorConstants.FALSE,
					VisitorConstants.visitAcceptable("値検証を失敗とする。")).put(
					ValidatorConstants.REQUIRED,
					VisitorConstants.visitAcceptable("値が入力されている状態")).put(
					ValidatorConstants.OR,
					VisitorConstants.visitAcceptable("論理和(全部評価する)")).put(
					ValidatorConstants.OROR,
					VisitorConstants.visitAcceptable("論理和")).put(
					ValidatorConstants.AND,
					VisitorConstants.visitAcceptable("論理積(全部評価する)")).put(
					ValidatorConstants.ANDAND,
					VisitorConstants.visitAcceptable("論理積")).put(
					ValidatorConstants.EQ,
					VisitorConstants.visitAcceptable("同値(全部評価する)")).put(
					ValidatorConstants.EQEQ,
					VisitorConstants.visitAcceptable("同値")).put(
					BranchByIdValidator.class,
					new Acceptable<BranchByIdValidator>() {
						public void accept(final Visitor visitor,
								final BranchByIdValidator v) {
							visitor.visit("リクエスト ID によって以下分岐する。");
							visitor.visit(v.getSwitchable());
						}
					}).put(BranchByNameIfExistsValidator.class,
					new Acceptable<BranchByNameIfExistsValidator>() {
						public void accept(final Visitor visitor,
								final BranchByNameIfExistsValidator v) {
							visitor.visit("リクエストされた変数名により以下分岐し、");
							visitor.visit(v.getValidatorIterable());
							visitor.visit("で全体の検証結果を判定する。");
							visitor.visit(v.getSwitchable());
						}
					}).put(BranchByNameValidator.class,
					new Acceptable<BranchByNameValidator>() {
						public void accept(final Visitor visitor,
								final BranchByNameValidator v) {
							visitor.visit("指定された変数名により以下分岐し、");
							visitor.visit(v.getValidatorIterable());
							visitor.visit("で全体の検証結果を判定する。");
							visitor.visit(v.getSwitchable());
						}
					}).put(CountValidator.class,
					IgnoreValidatorConstants.IGNORE_COUNT_VALIDATOR).put(
					DefaultValueValidator.class,
					new Acceptable<DefaultValueValidator>() {
						public void accept(final Visitor visitor,
								final DefaultValueValidator v) {
							visitor.visit("値を\"");
							visitor.visit(v.getValue());
							visitor.visit("\"に設定する。");
						}
					}).put(DumpValidator.class,
					IgnoreValidatorConstants.IGNORE_DUMP_VALIDATOR).put(
					EqualsValidator.class, new Acceptable<EqualsValidator>() {
						public void accept(final Visitor visitor,
								final EqualsValidator v) {
							visitor.visit("値が\"");
							visitor.visit(v.getObject());
							visitor.visit("\"と同値");
						}
					}).put(FormatValidator.class,
					new Acceptable<FormatValidator>() {
						public void accept(final Visitor visitor,
								final FormatValidator v) {
							visitor.visit(v.getFactory());
							visitor.visit("によって文字列に変換する。");
						}
					}).put(IfNotValidator.class,
					new Acceptable<IfNotValidator>() {
						public void accept(final Visitor visitor,
								final IfNotValidator v) {
							visitor.visit(v.getIfExpression());
							visitor.visit("そうでない場合");
							visitor.visit(v.getFalseExpression());
						}
					}).put(IfValidator.class, new Acceptable<IfValidator>() {
				public void accept(final Visitor visitor, final IfValidator v) {
					visitor.visit(v.getIfExpression());
					visitor.visit("である場合");
					visitor.visit(v.getTrueExpression());
					visitor.visit("そうでない場合");
					visitor.visit(v.getFalseExpression());
				}
			}).put(MaxLengthValidator.class,
					new Acceptable<MaxLengthValidator>() {
						public void accept(final Visitor visitor,
								final MaxLengthValidator v) {
							visitor.visit("文字列の長さが");
							visitor.visit(v.getValue());
							visitor.visit("以下");
						}
					}).put(MaxValidator.class, new Acceptable<MaxValidator>() {
				public void accept(
						final Visitor visitor,
						final MaxValidator v) {
					visitor.visit("数値が");
					visitor.visit(v.getValue());
					visitor.visit("以下");
				}
			}).put(MessageValidator.class, new Acceptable<MessageValidator>() {
				public void accept(final Visitor visitor,
						final MessageValidator v) {
					visitor.visit("メッセージ\"");
					visitor.visit(v.getMessage());
					visitor.visit("\"を出力する。");
				}
			}).put(MinLengthValidator.class,
					new Acceptable<MinLengthValidator>() {
						public void accept(
								final Visitor visitor,
								final MinLengthValidator v) {
							visitor.visit("文字列の長さが");
							visitor.visit(v.getValue());
							visitor.visit("以上");
						}
					}).put(MinValidator.class, new Acceptable<MinValidator>() {
				public void accept(
						final Visitor visitor,
						final MinValidator v) {
					visitor.visit("数値が");
					visitor.visit(v.getValue());
					visitor.visit("以上");
				}
			}).put(NotValidator.class, new Acceptable<NotValidator>() {
				public void accept(
						final Visitor visitor,
						final NotValidator v) {
					visitor.visit("以下の評価を否定する。");
					HtmlVisitorConstants.BLOCK.accept(visitor, v
							.getExpression());
				}
			}).put(ParseValidator.class, new Acceptable<ParseValidator>() {
				public void accept(
						final Visitor visitor,
						final ParseValidator v) {
					visitor.visit(v.getFactory());
					visitor.visit("によって文字列を変換する。");
				}
			}).put(RegExpIdValidator.class,
					new Acceptable<RegExpIdValidator>() {
						public void accept(final Visitor visitor,
								final RegExpIdValidator v) {
							visitor.visit("リクエスト ID が正規表現\"");
							visitor.visit(v.getPattern());
							visitor.visit("\"に合致");
						}
					}).put(RegExpValidator.class,
					new Acceptable<RegExpValidator>() {
						public void accept(final Visitor visitor,
								final RegExpValidator v) {
							visitor.visit("値が正規表現\"");
							visitor.visit(v.getPattern());
							visitor.visit("\"に合致");
						}
					}).put(RetainNamesValidator.class,
					new Acceptable<RetainNamesValidator>() {
						public void accept(final Visitor visitor,
								final RetainNamesValidator v) {
							visitor.visit("以下に挙げる変数名以外を取り除く");
							HtmlVisitorConstants.BLOCK.accept(visitor, v
									.getCollection());
						}
					}).put(SerialValidator.class,
					new Acceptable<SerialValidator>() {
						public void accept(final Visitor visitor,
								final SerialValidator v) {
							visitor.visit("以下の処理を順次実行し、");
							visitor.visit(v.getValidatorIterable());
							visitor.visit("で全体の検証結果を判定する。");
							HtmlVisitorConstants.ITERABLE.accept(visitor, v
									.getIterable());
						}
					}).put(TmpIndexValidator.class,
					new Acceptable<TmpIndexValidator>() {
						public void accept(final Visitor visitor,
								final TmpIndexValidator v) {
							visitor.visit("取得先インデックスを");
							visitor.visit(v.getTmpIndex());
							visitor.visit("に設定して以下を実行する。");
							HtmlVisitorConstants.BLOCK.accept(visitor, v
									.getExpression());
						}
					}).put(TmpKeyValidator.class,
					new Acceptable<TmpKeyValidator>() {
						public void accept(final Visitor visitor,
								final TmpKeyValidator v) {
							visitor.visit("取得先変数名を\"");
							visitor.visit(v.getTmpKey());
							visitor.visit("\"に設定して以下を実行する。");
							HtmlVisitorConstants.BLOCK.accept(visitor, v
									.getExpression());
						}
					}).put(ValidNamesValidator.class,
					new Acceptable<ValidNamesValidator>() {
						public void accept(final Visitor visitor,
								final ValidNamesValidator v) {
							visitor.visit("以下にあげる変数名のみ含まれている");
							HtmlVisitorConstants.BLOCK.accept(visitor, v
									.getCollection());
						}
					}).put(ValidValuesValidator.class,
					new Acceptable<ValidValuesValidator>() {
						public void accept(final Visitor visitor,
								final ValidValuesValidator v) {
							visitor.visit("以下にあげる値のいずれかである");
							HtmlVisitorConstants.BLOCK.accept(visitor, v
									.getCollection());
						}
					}).put(ValueLoopValidator.class,
					new Acceptable<ValueLoopValidator>() {
						public void accept(final Visitor visitor,
								final ValueLoopValidator v) {
							visitor.visit("変数一覧に対し以下の処理を順次実行し、");
							visitor.visit(v.getValidatorIterable());
							visitor.visit("で全体の検証結果を判定する。");
							HtmlVisitorConstants.BLOCK.accept(visitor, v
									.getExpression());
						}
					}).put(BranchByLocaleValidator.class,
					new Acceptable<BranchByLocaleValidator>() {
						public void accept(final Visitor visitor,
								final BranchByLocaleValidator v) {
							visitor.visit("ロケールによって以下分岐する。");
							visitor.visit(v.getSwitchable());
						}
					}).get());

	/**
	 * {@link woolpack.validator.ValidatorExpression}
	 * のコンストラクタツリーを日本語 HTML ドキュメントに変換するための
	 * {@link Visitor#setMap(Map)}に設定する{@link Map}。
	 * 
	 * @see #BASE
	 * 
	 */
	public static final Map<Object, Acceptable> MAP = Collections
			.unmodifiableMap(MapBuilder
					.get(new LinkedHashMap<Object, Acceptable>())
					.putAll(BASE)
					.putAll(DocTextConstants.BASE)
					.putAll(DocBaseConstants.BASE)
					.put(DelegationValidator.class,
							IgnoreValidatorConstants
							.IGNORE_DELEGATION_VALIDATOR)
					.put(Switchable.class, HtmlVisitorConstants.SWITCH).put(
							Map.class, HtmlVisitorConstants.MAP).put(
							FormatFactory.class,
							IgnoreTextConstants.IGNORE_FORMAT_FACTORY).put(
							Iterable.class, DomVisitorConstants.ITERABLE_COMMA)
					.put(Object.class, DomVisitorConstants.OBJECT).get());

	private DocValidatorConstants() {
	} // カバレージがここを通過してはいけない
}
