/*
 * Copyright (c) 2003, Morpho Project.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *	  this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *	  this list of conditions and the following disclaimer in the documentation
 *	  and/or other materials provided with the distribution.
 * 3. Neither the name of the Morpho Project nor the names of its contributors
 *	  may be used to endorse or promote products derived from this software
 *	  without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package jp.morpho.webapp.servlet.jsp.tagext.html;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;

import jp.morpho.webapp.action.ActionMappingManager;
import jp.morpho.webapp.servlet.http.HttpActionRequest;
import jp.morpho.webapp.servlet.http.impl.HttpActionRequestImpl;

/**
 * <P>
 * HTML のフォームを実装したタグハンドラです。
 * </P>
 * <P>
 * HTML のフォームは、文書の一部分を成し、通常の内容とマーク付け、そしてコントロールと呼ばれる特別な要素、更にこれらコントロールのラベルを含みます。
 * コントロールにはチェックボックス、ラジオボタン、メニューなどがあります。
 * ユーザは一般に、テキストを追加する、メニュー項目を選ぶ、等してこれらコントロールを変更してフォームを「完成」させ、その後フォーム処理のために Web サーバやメールサーバ等のエージェントへとフォームを提出します。
 * </P>
 * <P>
 * FORM の HTML 4 定義は次のとおりです。
 * <PRE>
 * &lt;!ELEMENT FORM - - (%block;|SCRIPT)+ -(FORM) -- interactive form --&gt;
 * &lt;!ATTLIST FORM
 *   %attrs;                              -- %coreattrs, %i18n, %events --
 *   action      %URI;          #REQUIRED -- server-side form handler --
 *   method      (GET|POST)     GET       -- HTTP method used to submit the form--
 *   enctype     %ContentType;  "application/x-www-form-urlencoded"
 *   accept      %ContentTypes; #IMPLIED  -- list of MIME types for file upload --
 *   name        CDATA          #IMPLIED  -- name of form for scripting --
 *   onsubmit    %Script;       #IMPLIED  -- the form was submitted --
 *   onreset     %Script;       #IMPLIED  -- the form was reset --
 *   accept-charset %Charsets;  #IMPLIED  -- list of supported charsets --
 *   &gt;
 * </PRE>
 * </P>
 * @author Kumiko Hiroi
 */
public class FormTag extends ControlTagSupport
{

	/**
	 * <P>
	 * FormTag を作成します。
	 * </P>
	 */
	public FormTag()
	{
		super();
	}

	/**
	 * <P>
	 * accept 属性を返します。
	 * </P>
	 * @return accept 属性
	 */
	public String getAccept()
	{
		return getAttributeMap().getString("accept");
	}

	/**
	 * <P>
	 * accept-charset 属性を返します。
	 * </P>
	 * @return accept-charset 属性
	 */
	public String getAcceptCharset()
	{
		return getAttributeMap().getString("accept-charset");
	}

	/**
	 * <P>
	 * action 属性を返します。
	 * </P>
	 * @return action 属性
	 */
	public String getAction()
	{
		return getAttributeMap().getString("action");
	}

	/**
	 * <P>
	 * enctype 属性を返します。
	 * </P>
	 * @return enctype 属性
	 */
	public String getEnctype()
	{
		return getAttributeMap().getString("enctype");
	}

	/**
	 * <P>
	 * method 属性を返します。
	 * </P>
	 * @return method 属性
	 */
	public String getMethod()
	{
		return getAttributeMap().getString("method");
	}

	/**
	 * <P>
	 * name 属性を返します。
	 * </P>
	 * @return name 属性
	 */
	public String getName()
	{
		return getAttributeMap().getString("name");
	}

	/**
	 * <P>
	 * onreset 属性を返します。
	 * </P>
	 * @return onreset 属性
	 */
	public String getOnreset()
	{
		return getAttributeMap().getString("onreset");
	}

	/**
	 * <P>
	 * onsubmit 属性を返します。
	 * </P>
	 * @return onsubmit 属性
	 */
	public String getOnsubmit()
	{
		return getAttributeMap().getString("onsubmit");
	}

	/**
	 * <P>
	 * accept 属性を設定します。
	 * </P>
	 * @param accept accept 属性
	 */
	public void setAccept(String accept)
	{
		getAttributeMap().putString("accept", accept);
	}

	/**
	 * <P>
	 * accept-charset 属性を設定します。
	 * </P>
	 * @param acceptCharset accept-charset 属性
	 */
	public void setAcceptCharset(String acceptCharset)
	{
		getAttributeMap().putString("accept-charset", acceptCharset);
	}

	/**
	 * <P>
	 * action 属性を設定します。
	 * </P>
	 * @param action action 属性
	 */
	public void setAction(String action)
	{
		getAttributeMap().putString("action", action);
	}

	/**
	 * <P>
	 * enctype 属性を設定します。
	 * </P>
	 * @param enctype enctype 属性
	 */
	public void setEnctype(String enctype)
	{
		getAttributeMap().putString("enctype", enctype);
	}

	/**
	 * <P>
	 * method 属性を設定します。
	 * </P>
	 * @param method method 属性
	 */
	public void setMethod(String method)
	{
		getAttributeMap().putString("method", method);
	}

	/**
	 * <P>
	 * name 属性を設定します。
	 * </P>
	 * @param name name 属性
	 */
	public void setName(String name)
	{
		getAttributeMap().putString("name", name);
	}

	/**
	 * <P>
	 * onreset 属性を設定します。
	 * </P>
	 * @param onreset onreset 属性
	 */
	public void setOnreset(String onreset)
	{
		getAttributeMap().putString("onreset", onreset);
	}

	/**
	 * <P>
	 * onsubmit 属性を設定します。
	 * </P>
	 * @param onsubmit onsubmit 属性
	 */
	public void setOnsubmit(String onsubmit)
	{
		getAttributeMap().putString("onsubmit", onsubmit);
	}

	/**
	 * <P>
	 * 終了タグの処理です。
	 * </P>
	 * @return EVAL_PAGE
	 * @see javax.servlet.jsp.tagext.Tag#doEndTag()
	 */
	public int doEndTag() throws JspException
	{
		StringBuffer buf = new StringBuffer();
		buf.append("</form>");

		try
		{
			JspWriter out = pageContext.getOut();
			out.print(buf.toString());
		}
		catch (IOException e)
		{
			throw new JspException(e.getMessage());
		}

		return super.doEndTag();
	}

	/**
	 * <P>
	 * 開始タグの処理です。
	 * </P>
	 * @return EVAL_BODY_BUFFERED
	 * @see javax.servlet.jsp.tagext.Tag#doStartTag()
	 */
	public int doStartTag() throws JspException
	{
		HttpActionRequest req = new HttpActionRequestImpl((HttpServletRequest)pageContext.getRequest());

		//FORMタグを作成します
		StringBuffer buf = new StringBuffer();
		buf.append("<form");

		//指定されていない属性にデフォルト値を設定します
		if (!this.getAttributeMap().containsKey("action"))
		{
			this.setAction(req.getRequestURI());
		}
		if (!this.getAttributeMap().containsKey("method"))
		{
			this.setMethod("post");
		}

		String keys[] = new String[this.getAttributeMap().size()];
		keys = (String[])this.getAttributeMap().keySet().toArray(keys);
		for (int i = 0; i < keys.length; i++)
		{
			buf.append(" ").append(keys[i]).append("=\"");
			if (!keys[i].equalsIgnoreCase("action"))
			{
				buf.append(this.getAttributeMap().getString(keys[i]));
			}
			else
			{
				HttpServletResponse response = (HttpServletResponse)pageContext.getResponse();
				String url = this.getAttributeMap().getString("action");
				buf.append(response.encodeURL(url));
			}
			buf.append("\"");
		}

		buf.append(">");

		ActionMappingManager amm = getActionMappingManager();

		//ステータスの hidden タグを作成します
		buf.append("<input type=\"hidden\" name=\"").append(amm.getStatusParameterName());
		buf.append("\" value=\"").append(req.getStatus());
		buf.append("\">");

		//アクションの hidden タグを作成します
		buf.append("<input type=\"hidden\" name=\"").append(amm.getActionParameterName());
		buf.append("\" value=\"\">");

		try
		{
			JspWriter out = pageContext.getOut();
			out.print(buf.toString());
		}
		catch (IOException e)
		{
			throw new JspException(e.getMessage());
		}

		return super.doStartTag();
	}

}
