/*
 * Copyright (c) 2009 The openGion Project.
 *
 * 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 org.opengion.hayabusa.resource;

import org.opengion.fukurou.util.StringUtil;
import java.io.UnsupportedEncodingException;

/**
 * 画面へのアクセス状況の情報を管理するクラスです。
 * 集計そのものは、UserInfo によりデータベース(GE15)に書き込まれます。
 * システムリソースのUSE_ACCESS_TOKEI_TABLE=true の場合のみ、DBに書き込まれますが、
 * データ集計そのものは、常に行っています。
 * このオブジェクトは、GUIInfo から、処理を委譲されて使用されます。
 *
 * ・accessCount   この画面へのアクセス数
 * ・errorCount    この画面でのエラー数
 * ・readCount     この画面で検索した件数
 * ・writeCount    この画面で登録した件数
 * ・dbTime        この画面にかかった累計ＤＢ処理時間(ms)
 * ・maxDbTime     この画面にかかった最大ＤＢ処理時間(ms)
 * ・maxQuery      最大ＤＢ処理時間を記録したときのSQL文
 *
 * @og.rev 4.0.0 (2004/12/31) 新規作成
 * @og.group リソース管理
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
final class GUIAccessCount {
	private final String   guiKey ;

	private int    accessCount	= 0;	// この画面へのアクセス数
	private int    errorCount	= 0;	// この画面でのエラー数
	private long   readCount	= 0;	// この画面で検索した件数
	private long   writeCount	= 0;	// この画面で登録した件数
	private long   dbTime		= 0;	// この画面にかかった累計ＤＢ処理時間(ms)
	private long   maxDbTime	= 0;	// この画面にかかった最大ＤＢ処理時間(ms)
	private String maxQuery		= null;	// 最大ＤＢ処理時間を記録したときのSQL文

	/**
	 * コンストラクター
	 *
	 * @param   guiKey   String    画面キー
	 */
	public GUIAccessCount( final String	guiKey ) {
		this.guiKey   = guiKey;
	}

	/**
	 * 画面情報 画面ID を取得します。
	 *
	 * @return   key   画面ID
	 */
	public String getKey() {
		return guiKey;
	}

	/**
	 * データベース検索した数と、掛かった時間(ms)を、セットします。
	 * これは、セキュリティ上の監視フラグで、不必要に、大量の
	 * データが検索された場合や、不正なデータアクセスがあるかどうかを
	 * 監視するための統計情報を取得します。
	 * 画面オブジェクトは、各ユーザー毎に作成されているため、個々の
	 * ユーザー毎/画面毎のアクセス状況を見ることが可能になります。
	 *
	 * @param  cnt データベース検索した数
	 * @param  time ＤＢ処理時間(ms)
	 * @param  query そのときのSQL文
	 */
	public void addReadCount( final int cnt,final long time,final String query ) {
		readCount += cnt ;
		dbTime += time ;
		if( maxDbTime < time ) {
			maxDbTime = time;
			maxQuery  = query;
		}
	}

	/**
	 * データベース検索した数と、掛かった時間(ms)を、取得します。
	 * これは、セキュリティ上の監視フラグで、不必要に、大量の
	 * データが検索された場合や、不正なデータアクセスがあるかどうかを
	 * 監視するための統計情報を取得します。
	 * 画面オブジェクトは、各ユーザー毎に作成されているため、個々の
	 * ユーザー毎/画面毎のアクセス状況を見ることが可能になります。
	 *
	 * @return  cnt データベース検索した数
	 */
	public long getReadCount() {
		return readCount ;
	}

	/**
	 * データベース登録した数を、セットします。
	 * これは、セキュリティ上の監視フラグで、不必要に、大量の
	 * データが登録された場合や、不正なデータアクセスがあるかどうかを
	 * 監視するための統計情報を取得します。
	 * 画面オブジェクトは、各ユーザー毎に作成されているため、個々の
	 * ユーザー毎/画面毎のアクセス状況を見ることが可能になります。
	 *
	 * @param  cnt データベース登録した数
	 * @param  time ＤＢ処理時間(ms)
	 * @param  query そのときのSQL文
	 */
	public void addWriteCount( final int cnt,final long time,final String query ) {
		writeCount += cnt ;
		dbTime += time ;
		if( maxDbTime < time ) {
			maxDbTime = time;
			maxQuery  = query;
		}
	}

	/**
	 * データベース登録した数を、取得します。
	 * これは、セキュリティ上の監視フラグで、不必要に、大量の
	 * データが登録された場合や、不正なデータアクセスがあるかどうかを
	 * 監視するための統計情報を取得します。
	 * 画面オブジェクトは、各ユーザー毎に作成されているため、個々の
	 * ユーザー毎/画面毎のアクセス状況を見ることが可能になります。
	 *
	 * @return  cnt データベース登録した数
	 */
	public long getWriteCount() {
		return writeCount ;
	}

	/**
	 * この画面へのアクセス回数を、＋１します。
	 * アクセス回数は、このメソッドの呼び出し回数のことです。
	 * 現状では、result.jsp 画面でセットすることで、アクセス数を
	 * 数えることにします。
	 *
	 */
	public void addAccessCount() {
		accessCount++ ;
	}

	/**
	 * この画面へのアクセス回数を、取得します。
	 * アクセス回数は、isWrite() メソッドの呼び出し回数のことです。
	 * このメソッドは、画面アクセス時に、チェックするたびに呼ばれます。
	 * 回数は、各JSP画面にこのチェックが入るはずなので、基本的な
	 * 画面の数（画面IDではなく、JSPファイル数）になります。
	 * ただし、forward や、 index では、このチェックは、行っていませんので
	 * カウントされません。
	 *
	 * @return  cnt 画面へのアクセス回数
	 */
	public int getAccessCount() {
		return accessCount ;
	}

	/**
	 * エラー発生時の件数を＋１します。
	 * これは、エラー発生時に呼び出すことで、エラー件数をチェックすることが
	 * 可能になります。
	 * 一般にエラーには、予期するエラー（必須入力登録漏れ等）と、予期しないエラー
	 * がありますが、ここでは、Java の Exceptionが発生する予期しないエラーの
	 * 件数をカウントします。
	 *
	 */
	public void addErrorCount() {
		errorCount++ ;
	}

	/**
	 * エラー発生時の件数を取得します。
	 * これは、エラー発生時に呼び出すことで、エラー件数をチェックすることが
	 * 可能になります。
	 * 一般にエラーには、予期するエラー（必須入力登録漏れ等）と、予期しないエラー
	 * がありますが、ここでは、Java の Exceptionが発生する予期しないエラーの
	 * 件数をカウントします。
	 *
	 * @return  エラー発生件数
	 */
	public int getErrorCount() {
		return errorCount ;
	}

	/**
	 * この画面にかかった累計ＤＢ処理時間(ms)を返します。
	 *
	 * @return  dbTime この画面にかかったＤＢ処理時間(ms)
	 */
	public long getQueryTime() {
		return dbTime ;
	}

	/**
	 * この画面にかかった最大ＤＢ処理時間(ms)を返します。
	 *
	 * @return  maxDbTime 最大ＤＢ処理時間(ms)
	 */
	public long getMaxQueryTime() {
		return maxDbTime ;
	}

	/**
	 * 最大ＤＢ処理時間を記録したときのSQL文を返します。
	 *
	 * @return  maxQuery 最大ＤＢ処理時間を記録したときのSQL文
	 *
	 * @og.rev 4.0.0.0 (2007/10/05) SQLServer 互換性の為、4000 Byte 以内に整形します。
	 * @og.rev 4.1.0.1 (2008/01/29) 戻り値を4000 Byte 以内にします。
	 */
	public String getMaxQuery() {
//		return ( maxQuery != null ) ? maxQuery : "" ;

		final String rtn ;
		if( maxQuery == null ) { rtn = ""; }
		else if( maxQuery.length() < 1300 ) { rtn = maxQuery; }
		else {
			String tmp ;
			try {
				byte[] byteValue = StringUtil.makeByte( maxQuery,"UTF-8" );
				tmp = new String( byteValue,"UTF-8" );
				if( tmp.length() > 1300 ) {
					tmp = tmp.substring( 0,1300 );
				}
			}
			catch( UnsupportedEncodingException ex ) {	// サポート必須のはず
				tmp = maxQuery.substring( 0,1300 );
			}
			rtn = tmp;
		}

		return rtn ;
	}
}
