//===========================================================================
// package
//===========================================================================
package jp.gr.java_conf.bugslife.form;

//===========================================================================
// import
//===========================================================================
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.*;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.validator.ValidatorForm;
import java.io.UnsupportedEncodingException;

import java.util.*;

import jp.gr.java_conf.bugslife.util.*;
import jp.gr.java_conf.bugslife.bug.*;
/**
 *<PRE>
 * ReportFormクラス
 *
 *</PRE>
 * @author 鰐川　正寛
 * @version 1.0.0
 */

public class ReportForm extends ValidatorForm {
//===========================================================================
// attributes
//===========================================================================
	/**
	 * action
	 */
	private String m_action;
	/**
	 * ReportType
	 */
	private String m_reportType;
	/**
	 * 発行日from
	 */
	private String m_fromDate;
	/**
	 * 発行日to
	 */
	private String m_toDate;
	/**
	 * 選択故障番号
	 */
	private String m_choiceBno;
	/**
	 * 発生工程
	 */
	private String[] m_processName;
	/**
	 * 対処方法
	 */
	private String[] m_resolution;
	/**
	 * 担当者
	 */
	private String[] m_dispach;
	/**
	 * 故障度
	 */
	private String[] m_severity;
	/**
	 * subsystem
	 */
	private String[] m_subsystem;
	/**
	 * 機能
	 */
	private String[] m_function;
	/**
	 * Log
	 */
	private Log log = LogFactory.getLog(this.getClass().getName());
//======================================
// other
//======================================
	/**
	 * where句
	 */
	private StringBuffer m_where = new StringBuffer();
	/**
	 * params
	 */
	private ArrayList m_params = new ArrayList();
	/**
	 * ヒット件数
	 */
	private int m_count;
//===========================================================================
// methods
//===========================================================================
	/**
	 * アクションの取得
	 * 
	 * @return アクション
	 */
	public String getAction()
	{
		return m_action;
	}
	/**
	 * アクションのセット
	 * 
	 * @param action アクション
	 */
	public void setAction(String action)
	{
		m_action = action;
	}
	/**
	 * ReportTypeの取得
	 * 
	 * @return ReportType
	 */
	public String getReportType()
	{
		return m_reportType;
	}
	/**
	 * ReportTypeのセット
	 * 
	 * @param ReportType ReportType
	 */
	public void setReportType(String reportType)
	{
		m_reportType = reportType;
	}
	/**
	 * 発行日fromの取得
	 * 
	 * @return 発行日from
	 */
	public String getFromDate()
	{
		return m_fromDate;
	}
	/**
	 * 発行日fromのセット
	 * 
	 * @param fromDate 発行日from
	 */
	public void setFromDate(String fromDate)
	{
		m_fromDate = fromDate;
	}
	/**
	 * 発行日toの取得
	 * 
	 * @return 発行日to
	 */
	public String getToDate()
	{
		return m_toDate;
	}
	/**
	 * 発行日toのセット
	 * 
	 * @param toDate 発行日to
	 */
	public void setToDate(String toDate)
	{
		m_toDate = toDate;
	}
	/**
	 * 選択故障番号の取得
	 * 
	 * @return 選択故障番号
	 */
	public String getChoiceBno()
	{
		return m_choiceBno;
	}
	/**
	 * 選択故障番号のセット
	 * 
	 * @param choiceBno 選択故障番号
	 */
	public void setChoiceBno(String choiceBno)
	{
		m_choiceBno = choiceBno;
	}
	/**
	 * 発生工程の取得
	 * 
	 * @return 発生工程
	 */
	public String[] getProcessName()
	{
		return m_processName;
	}
	/**
	 * 発生工程のセット
	 * 
	 * @param processName 発生工程
	 */
	public void setProcessName(String[] processName)
	{
		m_processName = processName;
	}
	/**
	 * 対処方法の取得
	 * 
	 * @return 対処方法
	 */
	public String[] getResolution()
	{
		return m_resolution;
	}
	/**
	 * 対処方法のセット
	 * 
	 * @param resolution 対処方法
	 */
	public void setResolution(String[] resolution)
	{
		m_resolution = resolution;
	}
	/**
	 * 担当者の取得
	 * 
	 * @return 担当者
	 */
	public String[] getDispach()
	{
		return m_dispach;
	}
	/**
	 * 担当者のセット
	 * 
	 * @param dispach 担当者
	 */
	public void setDispach(String[] dispach)
	{
		m_dispach = dispach;
	}
	/**
	 * 故障度の取得
	 * 
	 * @return 故障度
	 */
	public String[] getSeverity()
	{
		return m_severity;
	}
	/**
	 * 故障度のセット
	 * 
	 * @param severity 故障度
	 */
	public void setSeverity(String[] severity)
	{
		m_severity = severity;
	}
	/**
	 * 機能の取得
	 * 
	 * @return 機能
	 */
	public String[] getFunction()
	{
		return m_function;
	}
	/**
	 * 機能のセット
	 * 
	 * @param function 機能
	 */
	public void setFunction(String[] function)
	{
		m_function = function;
	}
	/**
	 * サブシステムの取得
	 * 
	 * @return サブシステム
	 */
	public String[] getSubsystem()
	{
		return m_subsystem;
	}
	/**
	 * サブシステムのセット
	 * 
	 * @param subsystem サブシステム
	 */
	public void setSubsystem(String[] subsystem)
	{
		m_subsystem = subsystem;
	}
//======================================
// other
//======================================
	/**
	 * where句の取得
	 * 
	 * @return where句
	 */
	public StringBuffer getWhere()
	{
		return m_where;
	}
	/**
	 * where句のセット
	 * 
	 * @param where where句
	 */
	public void setWhere(StringBuffer where)
	{
		m_where = where;
	}
	/**
	 * 検索パラメータ群の取得
	 * 
	 * @return 検索パラメータ群
	 */
	public ArrayList getParams()
	{
		return m_params;
	}
	/**
	 * 検索パラメータ群のセット
	 * 
	 * @param params 検索パラメータ群
	 */
	public void setParams(ArrayList params)
	{
		m_params = params;
	}
	/**
	 * 検索ヒット件数の取得
	 * 
	 * @return 検索ヒット件数
	 */
	public int getCount()
	{
		return m_count;
	}
	/**
	 * 検索ヒット件数のセット
	 * 
	 * @param count 検索ヒット件数
	 */
	public void setCount(int count)
	{
		m_count = count;
	}
//===========================================================================
// Public Methods
//===========================================================================
	/**
	* Reset all properties to their default values.
	*
	* @param mapping The mapping used to select this instance
	* @param request The servlet request we are processing
	*/
	public void reset(ActionMapping mapping, HttpServletRequest request) {
	
		//debug
		log.debug("reset");
		//encodeing セット
		try {
			request.setCharacterEncoding("SJIS");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		m_action = null;
		m_reportType = null;
		m_fromDate = null;
		m_toDate = null;
		m_choiceBno = null;
		//デフォルト値はアクションからセットするので、ここでは初期化するだけ
		m_processName = null;
		
		m_resolution = null;
		m_dispach = null;
		m_severity = null;
		m_function = null;
		//other 
		m_where = new StringBuffer();
		m_params = new ArrayList();
	}
	/**
	* Validate the properties that have been set from this HTTP request,
	* and return an <code>ActionErrors</code> object that encapsulates any
	* validation errors that have been found.  If no errors are found, return
	* <code>null</code> or an <code>ActionErrors</code> object with no
	* recorded error messages.
	*
	* @param mapping The mapping used to select this instance
	* @param request The servlet request we are processing
	*/
	public ActionErrors validate(ActionMapping mapping,
								 HttpServletRequest request) {
		ActionErrors errors = new ActionErrors();
		//debug
		log.debug("validate");
		
		//アクション
		if (Varidater.checkRequired(m_action, "action", errors)) {
			
			if (Varidater.checkRequired(m_reportType, "reportType", errors)) {
				//fromDate/toDate
				//どちらか指定されているか？
				if ((Varidater.isInput(m_fromDate)) || (Varidater.isInput(m_toDate))) {
					//指定あり
					parseDateSpan(m_fromDate, m_toDate, "issuDate", errors);
				}
				//選択バグ番号
				if (Varidater.isInput(m_choiceBno)) {
					parseChoiceBno("choiceBno", errors);
				}
				//発生工程
				parseSelection(m_processName, "issuPno", errors);
				//resolution
				parseSelection(m_resolution, "resolution", errors);
				//dispach
				parseSelection(m_dispach, "analyst", errors);
				//severity
				parseSelection(m_severity, "severity", errors);
				//milestone
				parseSelection(m_function, "functionName", errors);
				//subsystem
				parseSelection(m_subsystem, "subsystem", errors);
				
/*---------------------------
				//なにも指定されいなければエラーとする
				if (m_where.length() == 0) {
					Varidater.addErrors(Varidater.REQUIRED_MSG, "serchParam", errors);
				}
---------------------------*/
				
				
			}
		}
		
		return errors;
	}
//===========================================================================
// parser Methods
//===========================================================================
	/**
	 * 故障番号の解析
	 * 
	 * @return 故障番号
	 */
	private void parseChoiceBno(String name, ActionErrors errors) {
		
		StringBuffer where = new StringBuffer();
		
		//カンマで分解しながら、中を解析していく
		StringTokenizer st = new StringTokenizer(m_choiceBno, ",");
		while (st.hasMoreTokens()) {
			String token = st.nextToken();
			//tokenは空か？
			if ((token != null) && (token.length() > 0)) {
				//空でなければ
				
				//範囲指定チェック
				int offset = token.indexOf("-");
				//範囲指定ではない
				if (offset == -1) {
					//数値チェック
					if (Varidater.checkNumeric(token, name, errors)) {
						//where句の生成
						appendOR(where, "A.bno = ?");
						m_params.add(new Integer(token));
					}
				//範囲指定である
				} else {
					String from = token.substring(0,offset).trim();
					String to = token.substring(offset+1).trim();
					//from指定/to指定あり
					if ((from.length() > 0) && ((to.length() > 0))) {
						
						//where句の生成
						appendOR(where, "(A.bno >= ? AND bno <= ?)");
						if (Varidater.checkNumeric(from, name, errors)) {
							m_params.add(new Integer(from));
						}
						if (Varidater.checkNumeric(to, name, errors)) {
							m_params.add(new Integer(to));
						}
					//from指定のみ
					} else if (from.length() > 0) {
						appendOR(where, "A.bno >= ? ");
						
						if (Varidater.checkNumeric(from, name, errors)) {
							m_params.add(new Integer(from));
						}
					//to指定のみ
					} else {
						appendOR(where, "A.bno <= ? ");
						if (Varidater.checkNumeric(to, name, errors)) {
							m_params.add(new Integer(to));
						}
					}
				}
			}
		}
		
		//検索条件の括弧を閉じる
		termWhere(where);
		
		//debug
		log.debug("parseChoiceBno:where = " + where);
		
		//他の条件とANDで結ぶ
		appendAND(m_where, where);
		
	}
	/**
	 * 選択項目の解析
	 * 
	 */
	private void parseSelection(String[] target, String name, ActionErrors errors) {
		
		//指定無しの場合はなにもしない
		if ((target == null) || (target.length == 0)) {
			return;
		}
		
		StringBuffer where = new StringBuffer();
		
		for(int i = 0; i < target.length; i++) {
			//ダミーを選択していなければ
			if (! target.equals("00")) {
				//where句に追加
				if (name.equals("analyst")) {
					//analystだけは数値なのでIntegerに変換する必要がある。
					appendOR(where, "A." + name + " = ?");
					m_params.add(new Integer(target[i]));
				} else {
					appendOR(where, "A." + name + " = ?");
					m_params.add(target[i]);
				}
			}
		}
		
		//検索条件の括弧を閉じる
		termWhere(where);
		
		//debug
		log.debug("parseSelection:where = " + where);
		
		//他の条件とANDで結ぶ
		appendAND(m_where, where);
		
	}
	/**
	 * 日付間隔の解析
	 * 
	 */
	private void parseDateSpan(String from, String to, String name, ActionErrors errors) {
		
		StringBuffer where = new StringBuffer();
		boolean err = false;
		Date fromDate = null;
		Date toDate = null;
		
		//fromのチェック
		if (Varidater.isInput(from)) {	//指定あり
			if (Varidater.checkDate(from, name+"From", Converter.SHORT_DATE_PATTAN, errors)) {
				//エラーでなければ
				fromDate = Varidater.parseDate(from, Converter.SHORT_DATE_PATTAN);
			} else {
				err = true;		//エラーあり
			}
		}
		//toの解析
		if (Varidater.isInput(from)) {	//指定あり
			if (Varidater.checkDate(from, name+"To", Converter.SHORT_DATE_PATTAN, errors)) {
				//エラーでなければ
				toDate = Varidater.parseDate(to, Converter.SHORT_DATE_PATTAN);
			} else {
				err = true;		//エラーあり
			}
		}
		
		//ここまででエラーがあれば進めない
		if (err) {
			return;
		}
		
		//debug
		log.debug("fromDate = " + fromDate + " toDate =" + toDate);
		
		//比較
		if ((fromDate != null) && (toDate != null)) {		//両方指定
			//fromはtoより前か？
			if (! fromDate.before(toDate)) {
				//でなければ、エラー
				Varidater.addErrors(Varidater.INVALID_DATE_MSG, name+"From", errors);
				return;	//ここまで
				
			} else {
				//where句の生成
				where.append("(? <= A." + name + " AND A." + name + " <= ?)");
				m_params.add(fromDate);
				m_params.add(toDate);
			}
		} else if (fromDate != null) {
			//from指定の生成
			where.append("(? <= A." + name + ")");
			m_params.add(fromDate);
		} else {
			//to指定の生成
			where.append("(A." + name + " <= ?)");
			m_params.add(toDate);
		}
		//debug
		log.debug("parseDateSpan:where = " + where);
		
		//他の条件とANDで結ぶ
		appendAND(m_where, where);
		
	}
//===========================================================================
// private Methods
//===========================================================================
	/**
	 * OR条件の追加処理
	 */
	private void appendOR(StringBuffer where, String s) {
		
		if (where.length() == 0) {
			//最初のwhere句ならば、括弧で始める
			where.append("(");
		} else {
			//最初のwhere句でなければorで結ぶ
			where.append(" OR ");
		}
		where.append(s);
	}
	/**
	 * where句追加処理（条件の終了）
	 */
	private void termWhere(StringBuffer where) {
		
		if (where.length() != 0) {
			//条件があれば括弧を閉じる
			where.append(")");
		}
	}
	/**
	 * AND条件の追加処理
	 */
	private void appendAND(StringBuffer where, StringBuffer s) {
		
		//最初のwhere句でなければandで結ぶ
		if (s.length() > 0) {
			if (where.length() > 0) {
				where.append(" AND ");
			}
			where.append(s);
		}
	}
}