/*
 * 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 java.util.Map;
// import java.util.HashSet;
import java.util.LinkedHashMap ;
import java.util.Arrays;
import static org.opengion.fukurou.util.StringUtil.nval2;
import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;				// 6.1.0.0 (2014/12/26) refactoring

/**
 * systemId と lang に対応したコードデータを作成します。
 *
 * コードデータは、項目(CLM)に対して、複数のコード(CODE)を持っています。
 * この複数のコードを表示順に持つことで、プルダウンメニュー等の表示順を指定します。
 *
 * コードデータを作成する場合は、同一項目・コードで、作成区分違いの場合は、
 * 最も大きな作成区分を持つコードを使用します。
 * 作成区分(KBSAKU)は、他のリソースと異なり、基本的には使用しません。
 * これは、通常は項目単位に作成区分を持つべきところを、コード単位でしか
 * 持てないデータベースの設計になっている為です。アプリケーション側で設定条件を
 * きちんと管理すれば、作成区分を使用できますが、一般にはお奨めできません。
 *
 * @og.rev 4.0.0.0 (2004/12/31) 新規作成
 * @og.group リソース管理
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public final class CodeData {
//	6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止(IE8以降ブラウザ標準)
//	private final boolean USE_MULTI_KEY_SELECT = HybsSystem.sysBool( "USE_MULTI_KEY_SELECT" ) ;

	private static final String SPC = "";

	/** 内部データのカラム番号 {@value}	*/
	public static final int CLM			= 0 ;
	public static final int CODE		= 1 ;
	public static final int LNAME		= 2 ;
	public static final int SNAME		= 3 ;
	public static final int CODELVL		= 4 ;
	public static final int CODEGRP		= 5 ;
	public static final int CODE_PARAM	= 6 ;
	public static final int ROLES		= 7 ;
	public static final int SYSTEM_ID	= 8 ;
	public static final int KBSAKU		= 9 ;
	public static final int RSNAME		= 10;	// 4.3.8.0 (2009/08/01) spanが付かない名前短
	public static final int RLNAME		= 11;	// 5.6.8.2 (2013/09/20) rawLongLabel対応
	public static final int DESCRIPT	= 12;	// 6.2.0.0 (2015/02/27) description追加
	public static final int MAX_LENGTH	= 13;	// 6.2.0.0 (2015/02/27) 変更

	private final String	column ;			// 項目
	private final String[]	code ;				// コード
	private final String[]	longLabel ;			// コード名称(長)
	private final String[]	shortLabel ;		// コード名称(短)
	private final String[]	codeLevel ;			// コードレベル   ("1":option要素、"0":optgroup要素)
	private final String[]	codeGroup ;			// コードグループ (指定のグループキーで選別する)
	private final String[]	codeParam ;			// コードパラメータ
	private final String[]	roles ;				// ロール
	private final boolean[]	isUseFlag ;			// 5.1.9.0 (2010/08/01) サブセット化するときの有効/無効を指定
	private final int		size ;				// コード項目数
//	private final boolean	isMultiSelect ;		// マルチセレクト	6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止
	private final boolean	isUseLevel ;		// 5.1.9.0 (2010/08/01) コードレベル機能を利用するかどうか
	private final boolean	isUseParam ;		// 5.1.9.0 (2010/08/01) パラメータを利用するかどうか
	private final boolean	isUseGroup ;		// 5.1.9.0 (2010/08/01) コードグループを利用するかどうか
	private final boolean	isUseRoleMode ;		// 5.1.9.0 (2010/08/01) ロールモードを利用するかどうか

	private final RoleMode[] roleModes ;		// 4.3.0.0 (2008/07/04) ロールズとモードを管理するオブジェクト
	private final String[]	rawShortLabel;		// 4.3.8.0 (2009/08/01) spanが付かない名前短
	private final String[]	rawLongLabel;		// 5.6.8.2 (2013/09/20) 未加工名前長い
	private final String[]	description;		// 6.2.0.0 (2015/02/27) 概要説明

	/**
	 * 配列文字列のデータを元に、CodeDataオブジェクトを構築します。
	 * このコンストラクタは、他のパッケージから呼び出せないように、
	 * パッケージプライベートにしておきます。
	 * このコンストラクタは、マスタリソースファイルを想定しています。
	 *
	 * 引数の並び順は、CLM,CODE,LNAME,SNAME,CODELVL,CODEGRP,CODE_PARAM,ROLES,SYSTEM_ID,KBSAKU,RSNAME,RLNAME,DESCRIPT
	 *
	 * @og.rev 5.1.9.0 (2010/08/01) 新規追加
	 * @og.rev 6.3.6.0 (2015/08/16) System.arraycopy が使える箇所は、置き換えます。
	 *
	 * @param	clm 	カラム名
	 * @param	data	規定の順番の文字列配列を格納
	 * @param	useFlag	使用フラグ配列(サブセット化するときの有効/無効を指定)
	 */
	CodeData( final String clm, final Map<String,String[]> data , final boolean[] useFlag  ) {
		this( clm,data );

		if( useFlag != null && size == useFlag.length ) {
			// 6.3.6.0 (2015/08/16) System.arraycopy が使える箇所は、置き換えます。
			System.arraycopy( useFlag,0,isUseFlag,0,size );		// 6.3.6.0 (2015/08/16)
		}
	}

	/**
	 * 配列文字列のデータを元に、CodeDataオブジェクトを構築します。
	 * このコンストラクタは、他のパッケージから呼び出せないように、
	 * パッケージプライベートにしておきます。
	 * このコンストラクタは、マスタリソースファイルを想定しています。
	 *
	 * 引数の並び順は、CLM,CODE,LNAME,SNAME,CODELVL,CODEGRP,CODE_PARAM,ROLES,SYSTEM_ID,KBSAKU,RSNAME,RLNAME,DESCRIPT
	 *
	 * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応
	 * @og.rev 4.3.8.0 (2009/08/01) rawShortLabel追加
	 * @og.rev 4.3.8.0 (2009/08/01) グループ機能とパラメータの判定、isUseFlag フラグの追加
	 * @og.rev 5.2.2.0 (2010/11/01) "_" の取り扱いの変更
	 * @og.rev 5.6.8.2 (2103/09/20) rawlongLabel追加
	 * @og.rev 6.2.0.0 (2015/02/27) description 概要説明 追加
	 * @og.rev 6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止(IE8以降ブラウザ標準)
	 *
	 * @param	clm 	カラム名
	 * @param	data	規定の順番の文字列配列を格納
	 */
	CodeData( final String clm, final Map<String,String[]> data) {
		column  = clm;

		size = data.size();
		final String[] cdKeys = data.keySet().toArray( new String[size] );

		code		= new String[size];
		shortLabel	= new String[size];
		longLabel	= new String[size];
		codeLevel	= new String[size];
		codeGroup	= new String[size];
		codeParam	= new String[size];
		roles		= new String[size];
		roleModes	= new RoleMode[size];
		isUseFlag	= new boolean[size];		// 5.1.9.0 (2010/08/01) サブセットフラグの追加
		rawShortLabel	= new String[size];
		rawLongLabel	= new String[size];		// 5.6.8.2 (2103/09/20)
		description		= new String[size];		// 6.2.0.0 (2015/02/27) 概要説明 追加

//		// １文字目の重複判定により、マルチセレクトの可否を判断します。
//		final HashSet<String> set = new HashSet<>();
//		// 6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止(IE8以降ブラウザ標準)
//		boolean isSel = USE_MULTI_KEY_SELECT;	// 判定処理を行う。false なら判定処理も行わない。

		// 5.1.9.0 (2010/08/01) コードレベル、コードグループ、パラメータ、ロールの使用可否のフラグ
		boolean isLbl  = false;
		boolean isPrm  = false;
		boolean isRole = false;
		boolean isGrp  = false;

		for( int i=0; i<size; i++ ) {
			final String[] vals = data.get( cdKeys[i] );

			code[i] = nval2( vals[CODE],SPC );

			final String lname = nval2( vals[LNAME],SPC ) ;
			longLabel[i] = lname;

			// null か ゼロ文字列 : LNAME をセット
			// "_"                : ゼロ文字列
			// それ以外           : そのまま SNAME をセット
			shortLabel[i] = nval2( vals[SNAME]     ,lname , SPC );	// 5.2.2.0 (2010/11/01)

			codeLevel[i]  = nval2( vals[CODELVL]   , SPC ) ;
			codeGroup[i]  = nval2( vals[CODEGRP]   , SPC ) ;
			codeParam[i]  = nval2( vals[CODE_PARAM], SPC ) ;
			roles[i]	  = nval2( vals[ROLES]     , SPC ) ;

			// 5.1.9.0 (2010/08/01) コードレベル機能と、パラメータの使用判定
			if( !isLbl )  { isLbl  = "0".equals(   codeLevel[i] );	}
			if( !isPrm )  { isPrm  = ! SPC.equals( codeParam[i] );	}
			if( !isRole ) { isRole = ! SPC.equals( roles[i] );		}
			if( !isGrp )  { isGrp  = ! SPC.equals( codeGroup[i] );	}

			roleModes[i]	= RoleMode.newInstance( roles[i] );			// ロールモード
			rawShortLabel[i]= nval2( vals[RSNAME] , lname , SPC  );		// 5.2.2.0 (2010/11/01)
			rawLongLabel[i]	= nval2( vals[RLNAME] , lname , SPC  );		// 5.6.8.2 (2013/09/20)
			description[i]	= nval2( vals[DESCRIPT]       , SPC  );		// 6.2.0.0 (2015/02/27)

//			// 6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止(IE8以降ブラウザ標準)
//			if( isSel && lname.length() > 0 ) {
//				isSel = set.add( lname.substring(0,1) );	// 重複時は false
//			}
		}

		Arrays.fill( isUseFlag,true );	// 5.1.9.0 (2010/08/01) サブセットフラグの追加

//		// 6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止(IE8以降ブラウザ標準)
//		isMultiSelect = USE_MULTI_KEY_SELECT && ! isSel ;	// flag の反転に注意
		isUseLevel    = isLbl;		// 5.1.9.0 (2010/08/01) コードレベル機能を利用するかどうか
		isUseParam    = isPrm;		// 5.1.9.0 (2010/08/01) パラメータを利用するかどうか
		isUseRoleMode = isRole;		// 5.1.9.0 (2010/08/01) ロールモードを利用するかどうか
		isUseGroup    = isGrp;		// 5.1.9.0 (2010/08/01) コードグループを利用するかどうか
	}

	/**
	 * コードデータのキーを返します。
	 *
	 * @return コードデータのキー
	 */
	public String getColumn() { return column; }

	/**
	 * コードデータのキーを返します。
	 *
	 * @param	seqNo	表示順
	 *
	 * @return コードデータのキー
	 */
	public String getCodeKey( final int seqNo ) { return code[seqNo] ; }

	/**
	 * コードデータの表示名を返します。
	 *
	 * @param	seqNo	表示順
	 *
	 * @return コードデータの表示名
	 */
	public String getLongLabel( final int seqNo ) { return longLabel[seqNo]; }

	/**
	 * コードデータの短縮表示名を返します。
	 *
	 * @param seqNo 表示順
	 *
	 * @return コードデータの短縮表示名
	 */
	public String getShortLabel( final int seqNo ) { return shortLabel[seqNo]; }

	/**
	 * コード階層を返します。
	 *
	 * 通常のメニューは、階層が "1" になります。optgroup要素として使用する場合は、
	 * 階層を "0" で登録します。
	 *
	 * @param seqNo 表示順
	 *
	 * @return コード階層( "1":option要素、"0":optgroup要素 )
	 */
	public String getCodeLevel( final int seqNo ) { return codeLevel[seqNo]; }

	/**
	 * このコードが、使用できるかどうかを、返します。
	 *
	 * コードグループや、コードリストなどで、サブセットを作成する場合、
	 * プルダウンなどの選択肢は、制限しますが、レンデラーのラベルは、制限しません。
	 * これは、既存データを表示させる必要がある為です。
	 * このフラグは、選択肢を作成するときに利用します。
	 * 標準状態で作成した場合は、すべての項目が、true になっています。
	 *
	 * @og.rev 5.1.9.0 (2010/08/01) 新規追加
	 *
	 * @param	seqNo	表示順
	 *
	 * @return 使用可能な場合は、true
	 */
	public boolean isUse( final int seqNo ) { return isUseFlag[seqNo]; }

	/**
	 * コードパラメータを返します。
	 *
	 * コードパラメータは、メニューの各要素(option要素)に設定するタグの内容を追記します。
	 * ここに記述した文字列をそのまま追記します。
	 *
	 * @param seqNo 表示順
	 *
	 * @return コードパラメータ
	 */
	public String getCodeParam( final int seqNo ) { return codeParam[seqNo]; }

	/**
	 * コードロールを取得します。
	 *
	 * @param	seqNo	表示順
	 *
	 * @return	コードロール
	 */
	public String getRoles( final int seqNo ) { return roles[seqNo]; }

	/**
	 * カラムオブジェクトのロールモードを返します。
	 *
	 * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応
	 *
	 * @param	seqNo	表示順
	 *
	 * @return カラムオブジェクトのロールモード
	 */
	public RoleMode getRoleMode( final int seqNo ) { return roleModes[seqNo]; }

	/**
	 * ロールモードを、使用しているかどうかを、返します。
	 *
	 * ロールモードを使用している場合は、ロール制御の処理が必要です。
	 * 使用している/いないを事前に判断することで、無駄な処理を削減できます。
	 *
	 * @og.rev 5.1.9.0 (2010/08/01) 新規追加
	 *
	 * @return ロールモードを使用している場合は、true
	 */
	public boolean useRoleMode() { return isUseRoleMode; }

	/**
	 * マッチするコードデータのアドレスを返します。
	 * 一致するデータが存在しない場合は、-1 を返します。
	 *
	 * @param	key	検索するキー文字列
	 *
	 * @return コードデータのアドレス(なければ、-1)
	 */
	public int getAddress( final String key ) {
		int selected = -1;
		for( int i=0; i<size; i++ ) {
			if( code[i].equals( key ) ) {
				selected = i;
				break;
			}
		}
		return selected;
	}

	/**
	 * コードデータの配列数を返します。
	 *
	 * @return コードデータの配列数
	 */
	public int getSize() { return size; }

//	/**
//	 * マルチ・キーセレクトを使用するかどうかを返します。
//	 * true：使用する。false:使用しない です。
//	 * 使用するにした場合でも、ラベルの先頭文字が重複しない場合は、
//	 * IEの自動選択機能によりセレクト可能なため、JavaScript は出力しません。
//	 *
//	 * @og.rev 6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止(IE8以降ブラウザ標準)
//	 * @return  選択リストで、マルチ・キーセレクトを使用するかどうか(true:使用する)
//	 */
//	public boolean useMultiSelect() { return isMultiSelect; }

	/**
	 * コードレベル機能を利用するかどうかを返します。
	 * true：使用する。false:使用しない です。
	 * コードレベル機能を利用する場合は、optgroup タグを出力します。
	 * 設定としては、レベル 0 に指定のカラムを optgroup として出力します。
	 *
	 * @og.rev 5.1.9.0 (2010/08/01) 新規追加
	 *
	 * @return  コードレベル機能を利用するかどうか(初期値:false:使用しない)
	 */
	public boolean useLevel() { return isUseLevel; }

	/**
	 * パラメータを利用するかどうかを返します。
	 * true：使用する。false:使用しない です。
	 * このパラメータは、class 属性として設定される値です。
	 * これを使用して、各種レイアウトなどの指定が可能です。
	 *
	 * @og.rev 5.1.9.0 (2010/08/01) 新規追加
	 *
	 * @return  パラメータを利用するかどうか(初期値:false:使用しない)
	 */
	public boolean useParam() { return isUseParam; }

	/**
	 * コードグループを利用するかどうかを返します。
	 * true：使用する。false:使用しない です。
	 * このコードグループは、リソースの引数で設定した CSV形式に
	 * 対して、値が設定されていたかどうかを返します。
	 * これにより、不要な処理を行う必要がなくなります。
	 *
	 * @og.rev 5.1.9.0 (2010/08/01) 新規追加
	 *
	 * @return  パラメータを利用するかどうか(初期値:false:使用しない)
	 */
	public boolean useGroup() { return isUseGroup; }

	/**
	 * オブジェクトの識別子として，詳細なコード情報を返します。
	 * キー：ラベル　・・の繰り返し文字列を返します。
	 *
	 * @og.rev 4.1.0.0 (2008/01/18) 新規追加
	 *
	 * @return  詳細なコード情報
	 */
	public String toCodeString() {
		final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
		for( int i=0; i<size; i++ ) {
			final String key = code[i] + ":" ;
			if( ! longLabel[i].startsWith( key ) ) {
				rtn.append( key );
			}
			rtn.append( longLabel[i] );
			rtn.append( ' ' );		// 6.0.2.5 (2014/10/31) char を append する。
		}
		return rtn.toString().trim();
	}

	/**
	 * コードデータの短縮表示名(spanタグ無し)を返します。
	 *
	 * @og.rev 4.3.8.0 (2009/08/01) 新規追加
	 *
	 * @param seqNo 表示順
	 *
	 * @return コードデータの短縮表示名(spanタグ無し)
	 */
	public String getRawShortLabel( final int seqNo ) { return rawShortLabel[seqNo]; }

	/**
	 * 未加工の名前長を返します。
	 *
	 * @og.rev 5.6.8.2 (2013/09/13) 新規追加
	 *
	 * @param seqNo 表示順
	 *
	 * @return コードデータの短縮表示名(spanタグ無し)
	 */
	public String getRawLongLabel( final int seqNo ) { return rawLongLabel[seqNo]; }

	/**
	 * 概要説明 を返します。
	 *
	 * この概要説明は、個々の コードに対する説明です。
	 * optionタグに、title属性として使用すれば、説明文になります。
	 *
	 * @og.rev 6.2.0.0 (2015/02/27) description 概要説明 追加
	 *
	 * @param seqNo 表示順
	 *
	 * @return コードデータの概要説明
	 */
	public String getDescription( final int seqNo ) { return description[seqNo]; }

	/**
	 * 指定のコードに限定された CodeData を構築して返します。
	 * このサブセットは、コードのCSV文字列に基づいて作成されます。
	 *
	 * この CodeData は、本当のサブセットではなく、プルダウンメニューなどの選択肢のリストを
	 * 制限します。これは、一覧表示(レンデラー)では、すべての既存の設定値を表示しておく
	 * 必要があるからです。そして、変更時(エディター)に、選択肢を制限します。
	 *
	 * 引数の codeCsv が、null,ゼロ文字列の場合は、自分自身を返します。(同一です)
	 *
	 * @og.rev 5.1.9.0 (2010/08/01) 新規追加
	 * @og.rev 5.6.8.2 (2013/09/20) rawLongLabel対応
	 * @og.rev 6.2.0.0 (2015/02/27) description 概要説明 追加
	 *
	 * @param	codeCsv	指定のコードをカンマで連結されたもの
	 *
	 * @return 指定のコードに限定された CodeData
	 * @og.rtnNotNull
	 */
	public CodeData subsetList( final String codeCsv ) {
		if( codeCsv == null || codeCsv.isEmpty() ) {
			return this;
		}

		final String codes = "," + codeCsv + "," ;

		boolean[] useFlag = new boolean[size] ;

		final Map<String,String[]> data = new LinkedHashMap<>();
		for( int adrs=0; adrs<size; adrs++ ) {
			final String key = code[adrs] ;
			useFlag[adrs] = codes.indexOf( "," + key + "," ) >= 0 ;	// 存在する場合のみ、true
			String[] vals = new String[MAX_LENGTH];
			vals[CLM]		= column ;
			vals[CODE]		= key ;
			vals[LNAME]		= longLabel[adrs] ;
			vals[SNAME]		= shortLabel[adrs] ;
			vals[CODELVL]	= codeLevel[adrs] ;
			vals[CODEGRP]	= codeGroup[adrs] ;
			vals[CODE_PARAM]= codeParam[adrs] ;
			vals[ROLES]		= roles[adrs] ;
			vals[SYSTEM_ID]	= null ;
			vals[KBSAKU]	= null ;
			vals[RSNAME]	= rawShortLabel[adrs] ;
			vals[RLNAME]	= rawLongLabel[adrs] ;	// 5.6.8.2 (2013/09/20)
			vals[DESCRIPT]	= description[adrs] ;	// 6.2.0.0 (2015/02/27)

			data.put( key,vals );
		}

		return new CodeData( column,data,useFlag );
	}

	/**
	 * 指定のgroupに所属する限定された CodeData を構築して返します。
	 * このサブセットは、コードグループのCSV文字列に指定に基づいて作成されます。
	 *
	 * この CodeData は、本当のサブセットではなく、プルダウンメニューなどの選択肢のリストを
	 * 制限します。これは、一覧表示(レンデラー)では、すべての既存の設定値を表示しておく
	 * 必要があるからです。そして、変更時(エディター)に、選択肢を制限します。
	 *
	 * 引数の group が、null,ゼロ文字列、または、内部でグループを使用していない場合は、
	 * 自分自身を返します。(同一です)
	 * 引数の group も、内部設定のグループも、CSV形式CSV で複数のグループを指定できます。
	 * この場合は、各グループのうち、どれか一つでも該当すれば、使用(true)になります。
	 *
	 * @og.rev 5.1.9.0 (2010/08/01) 新規追加
	 * @og.rev 5.6.8.0 (2013/09/20) rawLongLabel対応
	 * @og.rev 6.2.0.0 (2015/02/27) description 概要説明 追加
	 *
	 * @param	group	指定のコードグループのCSV文字列
	 *
	 * @return 指定のgroupに所属する限定された CodeData
	 * @og.rtnNotNull
	 */
	public CodeData subsetGroup( final String group ) {
		if( group == null || group.isEmpty() || !isUseGroup ) {
			return this;
		}

		final String[] keys = group.split( "," ) ;

		boolean[] useFlag = new boolean[size] ;

		final Map<String,String[]> data = new LinkedHashMap<>();
		for( int adrs=0; adrs<size; adrs++ ) {
			final String cdGrp = codeGroup[adrs];

			boolean flag = SPC.equals( cdGrp );
			if( !flag ) {
				final String grpCsv = "," + cdGrp + "," ;
				for( int i=0; i<keys.length; i++ ) {
					flag = grpCsv.indexOf( keys[i] ) >= 0 ;
					if( flag ) { break; }
				}
			}

			useFlag[adrs] = flag;

			String[] vals = new String[MAX_LENGTH];
			vals[CLM]		= column ;
			vals[CODE]		= code[adrs] ;
			vals[LNAME]		= longLabel[adrs] ;
			vals[SNAME]		= shortLabel[adrs] ;
			vals[CODELVL]	= codeLevel[adrs] ;
			vals[CODEGRP]	= codeGroup[adrs] ;
			vals[CODE_PARAM]= codeParam[adrs] ;
			vals[ROLES]		= roles[adrs] ;
			vals[SYSTEM_ID]	= null ;
			vals[KBSAKU]	= null ;
			vals[RSNAME]	= rawShortLabel[adrs] ;
			vals[RLNAME]	= rawLongLabel[adrs] ;	// 5.6.8.0 (2013/09/20)
			vals[DESCRIPT]	= description[adrs] ;	// 6.2.0.0 (2015/02/27)

			data.put( code[adrs],vals );
		}

		return new CodeData( column,data,useFlag );
	}

	/**
	 * 指定のコードに限定された CodeData を構築して返します。
	 * このサブセットは、ロールの指定に基づいて作成されます。
	 *
	 * この CodeData は、本当のサブセットではなく、プルダウンメニューなどの選択肢のリストを
	 * 制限します。これは、一覧表示(レンデラー)では、すべての既存の設定値を表示しておく
	 * 必要があるからです。そして、変更時(エディター)に、選択肢を制限します。
	 *
	 * 引数の role が、null または、内部でロールを使用していない場合は、自分自身を返します。(同一です)
	 *
	 * @og.rev 5.1.9.0 (2010/08/01) 新規追加
	 * @og.rev 5.6.8.2 (2013/09/13) rawLongLabel対応
	 * @og.rev 6.2.0.0 (2015/02/27) description 概要説明 追加
	 *
	 * @param	userRole	指定のロール(ユーザーロール)
	 *
	 * @return 指定のコードに限定された CodeData
	 * @og.rtnNotNull
	 */
	public CodeData subsetRole( final RoleMode userRole ) {
		if( userRole == null || !isUseRoleMode ) {
			return this;
		}

		boolean[] useFlag = new boolean[size] ;

		final Map<String,String[]> data = new LinkedHashMap<>();
		for( int adrs=0; adrs<size; adrs++ ) {
			final byte rw = userRole.getAccessBitMode( roleModes[adrs] );

			useFlag[adrs] = RoleMode.isWrite( rw ) ;	// 書き込み可能な場合のみ、true

			String[] vals = new String[MAX_LENGTH];
			vals[CLM]		= column ;
			vals[CODE]		= code[adrs] ;
			vals[LNAME]		= longLabel[adrs] ;
			vals[SNAME]		= shortLabel[adrs] ;
			vals[CODELVL]	= codeLevel[adrs] ;
			vals[CODEGRP]	= codeGroup[adrs] ;
			vals[CODE_PARAM]= codeParam[adrs] ;
			vals[ROLES]		= roles[adrs] ;
			vals[SYSTEM_ID]	= null ;
			vals[KBSAKU]	= null ;
			vals[RSNAME]	= rawShortLabel[adrs] ;
			vals[RLNAME]	= rawLongLabel[adrs] ;
			vals[DESCRIPT]	= description[adrs] ;	// 6.2.0.0 (2015/02/27)

			data.put( code[adrs],vals );
		}

		return new CodeData( column,data,useFlag );
	}

	/**
	 * オブジェクトの識別子として，詳細なコード情報を返します。
	 *
	 * @og.rev 4.1.0.0 (2008/01/18) メソッド修正(改行コード削除)
	 *
	 * @return  詳細なコード情報
	 * @og.rtnNotNull
	 */
	@Override
	public String toString() {
		return "column = " + toCodeString() ;
	}
}
