package online.struts.chain.command;

import online.struts.action.UniForm;
import online.struts.mapping.RequestMapping;

import org.apache.commons.chain2.Processing;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionForm;
import org.apache.struts.chain.commands.ActionCommand;
import org.apache.struts.chain.contexts.ActionContext;
import org.apache.struts.chain.contexts.ServletActionContext;
import org.apache.struts.config.ActionConfig;

/**
 * コマンド処理クラス
 *
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public final class ActionRequest {

	/**
	 * コンストラクタ
	 */
	private ActionRequest() {
		throw new AssertionError();
	}

	/**
	 * コマンド実行
	 *
	 * @param context コンテキスト
	 * @param action コマンドリクエスト
	 * @return 処理結果
	 */
	public static Processing execute(final ActionContext<String, Object> context,
					final CommandRequest action) {
		// キャスト
		if (!ServletActionContext.class.isInstance(context)) {
			throw new IllegalStateException(String.valueOf(context));
		}
		ServletActionContext sac = ServletActionContext.class.cast(context);

		ActionConfig ac = context.getActionConfig();
		if (!RequestMapping.class.isInstance(ac)) {
			return Processing.CONTINUE;
		}
		RequestMapping mapping = RequestMapping.class.cast(ac);

		ActionForm form = context.getActionForm();
		if (!UniForm.class.isInstance(form)) {
			return Processing.CONTINUE;
		}
		UniForm uf = UniForm.class.cast(form);

		return action.command(sac, mapping, uf);
	}

	/**
	 * 例外判断
	 * @param sac コンテキスト
	 * @return 例外が発生していた場合 true を返す。
	 */
	public static boolean isException(final ServletActionContext sac) {
		return sac.getRequest().getAttribute(Globals.EXCEPTION_KEY) != null;
	}

	/**
	 * 初回確認
	 * @param sac コンテキスト
	 * @param cls 確認クラス
	 * @return 初回の場合 true を返す。
	 */
	public static boolean isFirst(final ServletActionContext sac,
					final Class<? extends ActionCommand<
							String, Object, ActionContext<String, Object>>> cls) {
		String clazz = cls.getName();
		if (sac.getRequest().getAttribute(clazz) == null) {
			sac.getRequest().setAttribute(clazz, clazz);
			return true;
		}
		return false;
	}

	/**
	 * コマンドリクエストクラス
	 *
	 * @author Tadashi Nakayama
	 * @version 1.0.0
	 */
	public interface CommandRequest {
		/**
		 * コマンド処理
		 *
		 * @param sac サーブレットアクションコンテキスト
		 * @param mapping アクションマッピング
		 * @param uf 汎用フォーム
		 * @return 処理結果
		 */
		Processing command(ServletActionContext sac, RequestMapping mapping, UniForm uf);
	}
}
