/*
 * 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.ValidatorExpression;
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 ValidatorExpression}の
 * コンストラクタツリーを日本語 HTML ドキュメントに変換するための定数の集まり。
 * @author nakamura
 *
 */
public 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_CountValidator)
			.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_DumpValidator)
			.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 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_DelegationValidator)
			.put(Switchable.class, HtmlVisitorConstants.SWITCH)
			.put(Map.class, HtmlVisitorConstants.MAP)
			.put(FormatFactory.class, IgnoreTextConstants.IGNORE_FormatFactory)
			.put(Iterable.class, DomVisitorConstants.ITERABLE_COMMA)
			.put(Object.class, DomVisitorConstants.OBJECT)
			.get());
	
	private DocValidatorConstants(){}// カバレージがここを通過してはいけない
}
