/*
 * 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.hayabusa.common.HybsSystem;
import static org.opengion.fukurou.util.StringUtil.nval2;

/**
 * 画面オブジェクトの元となる 画面データを作成します。
 * 画面データは、言語(lang)に依存しない情報で、最終的な 画面オブジェクト内部で
 * 使用される 固定的なデータオブジェクトになります。
 *
 * @og.rev 4.0.0.0 (2004/12/31) 新規作成
 * @og.group リソース管理
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public final class GUIData {

	/** 内部データのカラム番号 {@value}	*/
	public static final int GUIKEY		= 0 ;
	public static final int GUILVL		= 1 ;
	public static final int LABEL_CLM	= 2 ;
	public static final int ADDRESS		= 3 ;
	public static final int SEQNO		= 4 ;
	public static final int GROUPS		= 5 ;
	public static final int CLASSIFY	= 6 ;
	public static final int ROLES		= 7 ;
	public static final int RWMODE		= 8 ;
	public static final int TARGET		= 9 ;
	public static final int PARAM		= 10 ;
	public static final int KBLINK		= 11 ;
//	public static final int DATA_SIZE	= 12 ;
	public static final int DYUPD		= 12 ; // 5.3.3.0 (2011/03/01) 更新日時追加
	public static final int FAQ			= 13; // 5.6.4.3 (2013/05/24)

	private final String	guiKey ;		// 画面ID
	private final int		guiLevel ;		// 画面階層
	private final String	lblClm ;		// 画面カラムID
	private final String	address ;		// アドレス
	private final String	realAddress ;	// 実行実アドレス
	private final int		seqno ;			// 表示順
	private final String	groups ;		// グループ
	private final String	classify ;		// 分類
	private final String	target ;		// ターゲット
	private final String	param ;			// 設定値(パラメータ),イメージアイコン設定にも使います。
	private final String	kblink ;		// リンク区分
	private final boolean	pageUse ;		// page が、アドレスに追加できるかどうか
	private final RoleMode	roleMode ;		// 4.3.0.0 (2008/07/04) ロールズとモードを管理するオブジェクト
	private final String	dyupd ;			// 5.3.3.0 (2011/03/01) 更新日時追加
	private final String	imageKey ;		// 5.5.2.5 (2012/05/21) イメージアイコンの値。null の場合は、画面ID
	private final boolean	faq ;			// 5.6.4.3 (2013/05/24) FAQが存在しているか

	private static final String CON_DIR = "/" + HybsSystem.getContextName() + "/";

	/**
	 * 配列文字列のデータを元に、GUIDataオブジェクトを構築します。
	 * このコンストラクタは、他のパッケージから呼び出せないように、
	 * パッケージプライベートにしておきます。
	 * このコンストラクタは、ＤＢリソースファイルを想定しています。
	 *
	 * @og.rev 4.3.3.7 (2008/11/22) https対応
	 * @og.rev 5.1.3.0 (2010/02/01) 画面ロールのroot の場合は、user が root 以外、アクセス禁止のはず
	 * @og.rev 5.3.3.0 (2011/03/01) 更新日時追加
	 * @og.rev 5.5.2.5 (2012/05/21) imageKey イメージアイコンの処理を追加
	 * @og.rev 5.6.4.3 (2013/05/24) faqt追加
	 *
	 * @param	data	GUIKEY,GUILVL,LABEL_CLM,ADDRESS,SEQNO,GROUPS,CLASSIFY,ROLES,RWMODE,TARGET,KBLINK
	 */
	GUIData( final String[] data ) {
		guiKey		= data[GUIKEY].intern() ;					// 画面ID
		guiLevel	= Integer.parseInt( data[GUILVL] );			// 画面階層
		lblClm 		= nval2( data[LABEL_CLM],guiKey ) ;			// 画面カラムID
		address 	= data[ADDRESS].intern() ;					// アドレス
		seqno		= Integer.parseInt( data[SEQNO] );			// 表示順
		groups		= nval2( data[GROUPS] , null ) ;			// グループ
		classify	= nval2( data[CLASSIFY] , "" ) ;			// 分類
//		roleMode	= RoleMode.newInstance( data[ROLES],data[RWMODE] );	// ロールモード Ver.5.1.3.0 削除
		target		= nval2( data[TARGET] , null ) ;			// ターゲット

		// realAddress と pageUse を設定します。
		// 3.5.5.0 (2004/03/12) kblink の設定方法を見直し
		// 4.3.3.7 (2008/11/22) https対応
//		if( address.startsWith( "http://" ) || address.startsWith( "." ) ) {
		if( address.startsWith( "http://" ) || address.startsWith( "https://" ) || address.startsWith( "." ) ) {
			kblink = "http";
			pageUse = false;
			realAddress = address;
		}
		else {
			pageUse = true;
			kblink = nval2( data[KBLINK] , "jsp" ) ;			// リンク区分
			if( kblink.startsWith( "/" ) ) {
				realAddress = ( kblink + "/" + address + "/" ) ;
			}
			else {
				realAddress = ( CON_DIR + kblink + "/" + address + "/" ) ;
//				realAddress = ( "/" + HybsSystem.getContextName() + "/" + kblink +
//						"/" + address + "/" ) ;
			}
		}

		// 4.0.0 (2005/01/31) param を追加します。
		String paramTmp = data[PARAM] ;	// 設定値(パラメータ)
		if( paramTmp != null && paramTmp.length() > 0 ) {
			param = paramTmp.intern() ;
		}
		else {
			param    = "" ;
		}

		// 5.5.2.5 (2012/05/21) イメージアイコンの処理。既存の param 設定と分けておきます。(将来的にはDBから読み取りたい)
		int indx1 = param.indexOf( "IMAGE_KEY=" );
		if( indx1 >= 0 ) {
			indx1 = indx1+"IMAGE_KEY=".length() ;		// 指定の文字列まで進めておく。
			int indx2 = param.indexOf( "&",indx1 );	// パラメータの区切り記号。ない＝最後
			if( indx2 >= 0 ) {
				imageKey = param.substring( indx1, indx2 );
			}
			else {
				imageKey = param.substring( indx1 );
			}
		}
		else {
			imageKey = guiKey ;		// 5.5.2.5 (2012/05/21) イメージアイコンの処理を追加
		}

		// 5.1.3.0 (2010/02/01) 画面ロールのroot の場合は、user が root 以外、アクセス禁止のはず
		// ここでは、RoleMode で、共通化を図っているため、"root" を、"r00t" に置換えます。
		String roles = data[ROLES];
		if( "root".equals( roles ) ) { roles = "r00t" ; }
		roleMode	= RoleMode.newInstance( roles,data[RWMODE] );	// ロールモード

		// 3.5.5.0 (2004/03/12) 実行実アドレスを求めます。
//		if( address.startsWith( "http://" ) || address.startsWith( "." ) ) {
//			realAddress = address;
//			pageUse = false;
//		}
//		else {
//			realAddress = ( "/" + HybsSystem.getContextName() + "/" + kblink +
//								"/" + address + "/" ) ;
//			pageUse = true;
//		}

		dyupd = nval2( data[DYUPD] , "" ) ;
		
		faq = Boolean.parseBoolean( data[FAQ] ); // 5.6.4.3 (2013/06/24)
	}

	/**
	 * 画面オブジェクトのキーを返します。
	 *
	 * @return 画面オブジェクトのキー
	 */
	public String getGuiKey() { return guiKey; }

	/**
	 * 画面オブジェクトの階層レベルを返します。
	 *
	 * @return 画面オブジェクトの階層レベル
	 */
	public int getGuiLevel() { return guiLevel ; }

	/**
	 * 画面オブジェクトの画面カラムIDを返します。
	 * これは、同一画面ID(GUIKEY)で、ロール違いやアドレス違いにより
	 * 画面に表示する名称を変える場合に使用します。
	 *
	 * @return 画面オブジェクトの画面カラムID
	 */
	public String getLabelClm() { return lblClm ; }

	/**
	 * 画面オブジェクトのアドレスを返します。
	 *
	 * @return 画面オブジェクトのアドレス
	 */
	public String getAddress() { return address; }

	/**
	 * トップからの実行アドレス情報を取得します。
	 * コンテキスト名とリンク区分属性を利用して、サーバートップからのアドレスを
	 * 返します。ただし、GUIリソースに、http://～ または、.～ から始まるアドレスは
	 * そのまま、なにも変換せずに返します。
	 * param 属性がある場合は、引数として後ろに追加します。
	 *
	 * http://AAAA  ⇒  http://AAAA
	 * ../../AAAA/  ⇒  ../../AAAA/
	 * AAAA         ⇒  /CONTEXT_NAME/KBLINK/AAAA/
	 *
	 * @og.rev 3.5.5.0 (2004/03/12) 新規追加
	 * @og.rev 4.0.0.0 (2005/01/31) param 属性の追加
	 *
	 * @return	実行実アドレス
	 */
	public String getRealAddress() {
		return realAddress ;
	}

	/**
	 * トップからの実行アドレス情報を取得します。
	 * コンテキスト名とリンク区分属性を利用して、サーバートップからのアドレスを
	 * 返します。ただし、GUIリソースに、http://～ または、.～ から始まるアドレスは
	 * そのまま、なにも変換せずに返します。
	 * また、アドレスの最後がスラッシュ(/)で終了している場合は、page属性を追加します。
	 *
	 * http://AAAA  ⇒  http://AAAA
	 * ../../AAAA/  ⇒  ../../AAAA/
	 * AAAA         ⇒  /CONTEXT_NAME/KBLINK/AAAA/
	 *
	 * @og.rev 4.0.0.0 (2005/01/31) 新規追加
	 *
	 * @param    page          実行ページ(index.jsp など)
	 *
	 * @return	実行実アドレス
	 */
	public String getRealAddress( final String page ) {
		if( ! pageUse || page == null ) {
			return realAddress ;
		}
		else {
			return realAddress + page;
		}
	}

	/**
	 * 画面オブジェクトの表示順を返します。
	 *
	 * @return	画面オブジェクトの表示順
	 */
	public int getSeqno() { return seqno; }

	/**
	 * 画面オブジェクトのグループを返します。
	 *
	 * @return	画面オブジェクトのグループ
	 */
	public String getGroups() { return groups; }

	/**
	 * 画面オブジェクトの分類を返します。
	 *
	 * @return	画面オブジェクトの分類
	 */
	public String getClassify() { return classify; }

	/**
	 * 画面オブジェクトのロールズを返します。
	 *
	 * @return	画面オブジェクトのロールズ文字列
	 */
	public String getRoles() { return roleMode.getRoles(); }

	/**
	 * 画面オブジェクトのモード文字列を返します。
	 *
	 * @return	画面オブジェクトのモード文字列
	 */
	public String getMode() { return roleMode.getMode(); }

	/**
	 * ロールモード情報を取得します。
	 *
	 * @og.rev 4.3.0.0 (2008/07/04) 新規追加
	 *
	 * @return	ロールモード情報
	 */
	public RoleMode getRoleMode() { return roleMode ; }

	/**
	 * 画面オブジェクトのターゲットを返します。
	 *
	 * @return 画面オブジェクトのターゲット
	 */
	public String getTarget() { return target; }

	/**
	 * 画面オブジェクトのパラメータを返します。
	 *
	 * @return 画面オブジェクトのパラメータ
	 */
	public String getParam() { return param; }

	/**
	 * 画面オブジェクトのリンク区分を返します。
	 *
	 * @return 画面オブジェクトのリンク区分
	 */
	public String getKblink() { return kblink; }

	/**
	 * 画面オブジェクトの更新日時を返します。
	 *
	 * @og.rev 5.3.3.0 (2011/03/01) 新規追加
	 *
	 * @return 画面オブジェクトの更新日時
	 */
	public String getDyupd() { return dyupd; }
	
	/**
	 * 画面オブジェクトのFAQを返します。
	 *
	 * @return 画面オブジェクトのFAQ
	 */
	public boolean isFaq() { return faq; }
	
	/**
	 * イメージアイコンのキーを返します。
	 *
	 * 画面にアイコンを追加する場合、jsp/menuImage フォルダに、画面ID と同じ名称の
	 * 画像ファイルを置く必要があります。
	 * 本来は、画面リソース(GEA11)に、カラムを追加して対応すべきですが、互換性の関係より、
	 * PARAM 属性で、所定のキーを登録することで使えるようにします。
	 * この、PARAMは、画面アドレスの引数(たとえば、command=NEW など)を使うためのパラメータですが、
	 * アイコン割り当て(IMAGE_KEY=XXXX)を使用することで、XXXX をキーとして使います。
	 * IMAGE_KEY=XXXX が指定されない場合は、画面IDが、imageKey として返されます。
	 *
	 * @og.rev 5.5.2.5 (2012/05/21) 新規追加
	 *
	 * @return イメージアイコンのキー
	 */
	public String getImageKey() { return imageKey; }

	/**
	 * 画面オブジェクトへのアクセス可否を返します。
	 *
	 * @param	userRoles	ユーザーロール配列
	 *
	 * @return アクセスできる(true)/出来ない(false)
	 */
//	public boolean isAccess( final String[] userRoles ) {
//		return roleMode.isAccess( userRoles );
//	}

	/**
	 * この画面のアクセス条件を設定します。
	 * アクセス条件は、複数あるユーザーロールの中で、最大のアクセス条件を算出します。
	 * 例えば、AAA|BBB|CCC の３つのロールに、-r|-w|mr| のモードが設定されている場合、
	 * ユーザーが、AAA だけの場合は、-r ですが、AAA|BBB を持っている場合は、-w になります。
	 * さらに、BBB|CCC と持っている場合は、(-w:書き込み許可)と(mr:メニューから読取許可)の
	 * 権限により、mw:メニューからの書き込み許可が与えられます。
	 * 実際には、メニュー表示の可否は、ポップアップ系によく用いられますので、上記のような
	 * 許可が実際にあるかどうかは不明ですが、すべてのモードのOR条件での結合になります。
	 *
	 * @param	userRoles	ユーザーロール配列
	 * @param	isRoot	ルートロールフラグ
	 *
	 * @return  ビットモード配列 "--:000","-r:001","-w:010","mr:101","mw:110" に対応した数字(0,1,2,5,6)
	 */
//	public byte getAccessBitMode( final String[] userRoles,final boolean isRoot ) {
//		return roleMode.getAccessBitMode( userRoles,isRoot );
//	}

	/**
	 * 指定のユーザーロールに対する最終的なアクセス条件を取得します。
	 * アクセス条件は、複数あるユーザーロールの中で、最大のアクセス条件を算出します。
	 * 例えば、AAA(-r)|BBB(-w)|CCC(mr) の３つのロール/モードが設定されている場合、
	 * ユーザーが、AAA だけの場合は、-r ですが、AAA|BBB を持っている場合は、-w になります。
	 * さらに、BBB|CCC と持っている場合は、(-w:書き込み許可)と(mr:メニューから読取許可)の
	 * 権限により、mw:メニューからの書き込み許可が与えられます。
	 * モード指定がある場合は、AND演算になります。
	 * 例えば、AAA(-r)|BBB(-w)|CCC(mr) と BBB|CCC(-r) の場合、(-r)+(-w)+(mr)*(-r)=-w に
	 * なります。ロールは、OR ですが、モードは、同一ロールでのAND になります。
	 * 実際には、メニュー表示の可否は、ポップアップ系によく用いられますので、上記のような
	 * 許可が実際にあるかどうかは不明ですが、すべてのモードのOR条件での結合になります。
	 *
	 * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応
	 *
	 * @param other RoleMode ロールモード
	 *
	 * @return アクセスビット
	 */
//	public byte getAccessBitMode( final RoleMode other ) {
//		return roleMode.getAccessBitMode( other );
//	}

	/**
	 * オブジェクトの識別子として，詳細なユーザー情報を返します。
	 *
	 * @og.rev 5.3.3.0 (2011/03/01) 更新日時を追加
	 * @og.rev 5.6.4.3 (2013/05/24) faq
	 *
	 * @return  詳細な画面情報
	 */
	@Override
	public String toString() {
		StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
		rtn.append( "guiKey     :" ).append( guiKey      ).append( HybsSystem.CR );
		rtn.append( "guiLevel   :" ).append( guiLevel    ).append( HybsSystem.CR );
		rtn.append( "address    :" ).append( address     ).append( HybsSystem.CR );
		rtn.append( "realAddress:" ).append( realAddress ).append( HybsSystem.CR );
		rtn.append( "seqno      :" ).append( seqno       ).append( HybsSystem.CR );
		rtn.append( "classify   :" ).append( classify    ).append( HybsSystem.CR );
		rtn.append( "roles      :" ).append( getRoles()  ).append( HybsSystem.CR );
		rtn.append( "mode       :" ).append( getMode()   ).append( HybsSystem.CR );
		rtn.append( "target     :" ).append( target      ).append( HybsSystem.CR );
		rtn.append( "param      :" ).append( param       ).append( HybsSystem.CR );
		rtn.append( "kblink     :" ).append( kblink      ).append( HybsSystem.CR );
		rtn.append( "dyupd      :" ).append( dyupd       ).append( HybsSystem.CR );
		rtn.append( "faq        :" ).append( faq         ).append( HybsSystem.CR );
		return rtn.toString();
	}
}
