001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.hayabusa.resource;
017
018import java.util.Map;
019// import java.util.HashSet;
020import java.util.LinkedHashMap ;
021import java.util.Arrays;
022
023// import org.opengion.hayabusa.common.HybsSystem ;
024import static org.opengion.fukurou.util.StringUtil.nval2;
025import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;                              // 6.1.0.0 (2014/12/26) refactoring
026
027/**
028 * systemId と lang に対応したコードデータを作成します。
029 *
030 * コードデータは、項目(CLM)に対して、複数のコード(CODE)を持っています。
031 * この複数のコードを表示順に持つことで、プルダウンメニュー等の表示順を指定します。
032 *
033 * コードデータを作成する場合は、同一項目・コードで、作成区分違いの場合は、
034 * 最も大きな作成区分を持つコードを使用します。
035 * 作成区分(KBSAKU)は、他のリソースと異なり、基本的には使用しません。
036 * これは、通常は項目単位に作成区分を持つべきところを、コード単位でしか
037 * 持てないデータベースの設計になっている為です。アプリケーション側で設定条件を
038 * きちんと管理すれば、作成区分を使用できますが、一般にはお奨めできません。
039 *
040 * @og.rev 4.0.0.0 (2004/12/31) 新規作成
041 * @og.group リソース管理
042 *
043 * @version  4.0
044 * @author   Kazuhiko Hasegawa
045 * @since    JDK5.0,
046 */
047public final class CodeData {
048//      6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止(IE8以降ブラウザ標準)
049//      private final boolean USE_MULTI_KEY_SELECT = HybsSystem.sysBool( "USE_MULTI_KEY_SELECT" ) ;
050
051        private static final String SPC = "";
052
053        // 内部データのカラム番号
054        /** カラム番号 {@value}      */ public static final int CLM                  = 0 ;
055        /** カラム番号 {@value}      */ public static final int CODE                 = 1 ;
056        /** カラム番号 {@value}      */ public static final int LNAME                = 2 ;
057        /** カラム番号 {@value}      */ public static final int SNAME                = 3 ;
058        /** カラム番号 {@value}      */ public static final int CODELVL              = 4 ;
059        /** カラム番号 {@value}      */ public static final int CODEGRP              = 5 ;
060        /** カラム番号 {@value}      */ public static final int CODE_PARAM   = 6 ;
061        /** カラム番号 {@value}      */ public static final int ROLES                = 7 ;
062        /** カラム番号 {@value}      */ public static final int SYSTEM_ID    = 8 ;
063        /** カラム番号 {@value}      */ public static final int KBSAKU               = 9 ;
064        /** カラム番号 {@value}      */ public static final int RSNAME               = 10;   // 4.3.8.0 (2009/08/01) spanが付かない名前短
065        /** カラム番号 {@value}      */ public static final int RLNAME               = 11;   // 5.6.8.2 (2013/09/20) rawLongLabel対応
066        /** カラム番号 {@value}      */ public static final int DESCRIPT             = 12;   // 6.2.0.0 (2015/02/27) description追加
067
068//      public static final int MAX_LENGTH      = 13;   // 6.2.0.0 (2015/02/27) 変更
069        /** 内部データのカラム数 {@value} */
070        /* default */ static final int DATA_SIZE        = 13;   // 7.2.6.0 (2020/06/30) キーワード変更
071
072        private final String    column ;                        // 項目
073        private final String[]  code ;                          // コード
074        private final String[]  longLabel ;                     // コード名称(長)
075        private final String[]  shortLabel ;            // コード名称(短)
076        private final String[]  codeLevel ;                     // コードレベル   ("1":option要素、"0":optgroup要素)
077        private final String[]  codeGroup ;                     // コードグループ (指定のグループキーで選別する)
078        private final String[]  codeParam ;                     // コードパラメータ
079        private final String[]  roles ;                         // ロール
080        // 8.5.4.2 (2024/01/12) PMD 7.0.0 LinguisticNaming
081//      private final boolean[] isUseFlag ;                     // 5.1.9.0 (2010/08/01) サブセット化するときの有効/無効を指定
082        private final boolean[] useSubset ;                     // 5.1.9.0 (2010/08/01) サブセット化するときの有効/無効を指定
083        private final int               size ;                          // コード項目数
084//      private final boolean   isMultiSelect ;         // マルチセレクト      6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止
085        private final boolean   isUseLevel ;            // 5.1.9.0 (2010/08/01) コードレベル機能を利用するかどうか
086        private final boolean   isUseParam ;            // 5.1.9.0 (2010/08/01) パラメータを利用するかどうか
087        private final boolean   isUseGroup ;            // 5.1.9.0 (2010/08/01) コードグループを利用するかどうか
088        private final boolean   isUseRoleMode ;         // 5.1.9.0 (2010/08/01) ロールモードを利用するかどうか
089
090        private final RoleMode[] roleModes ;            // 4.3.0.0 (2008/07/04) ロールズとモードを管理するオブジェクト
091        private final String[]  rawShortLabel;          // 4.3.8.0 (2009/08/01) spanが付かない名前短
092        private final String[]  rawLongLabel;           // 5.6.8.2 (2013/09/20) 未加工名前長い
093        private final String[]  description;            // 6.2.0.0 (2015/02/27) 概要説明
094
095        /**
096         * 配列文字列のデータを元に、CodeDataオブジェクトを構築します。
097         * このコンストラクタは、他のパッケージから呼び出せないように、
098         * パッケージプライベートにしておきます。
099         * このコンストラクタは、マスタリソースファイルを想定しています。
100         *
101         * 引数の並び順は、CLM,CODE,LNAME,SNAME,CODELVL,CODEGRP,CODE_PARAM,ROLES,SYSTEM_ID,KBSAKU,RSNAME,RLNAME,DESCRIPT
102         *
103         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
104         * @og.rev 6.3.6.0 (2015/08/16) System.arraycopy が使える箇所は、置き換えます。
105         *
106         * @param       clm     カラム名
107         * @param       data    規定の順番の文字列配列を格納
108         * @param       useFlag 使用フラグ配列(サブセット化するときの有効/無効を指定)
109         */
110        /* default */ CodeData( final String clm, final Map<String,String[]> data , final boolean[] useFlag  ) {
111                this( clm,data );
112
113                if( useFlag != null && size == useFlag.length ) {
114                        // 6.3.6.0 (2015/08/16) System.arraycopy が使える箇所は、置き換えます。
115                        // 8.5.4.2 (2024/01/12) PMD 7.0.0 LinguisticNaming
116//                      System.arraycopy( useFlag,0,isUseFlag,0,size );         // 6.3.6.0 (2015/08/16)
117                        System.arraycopy( useFlag,0,useSubset,0,size );         // 6.3.6.0 (2015/08/16)
118                }
119        }
120
121        /**
122         * 配列文字列のデータを元に、CodeDataオブジェクトを構築します。
123         * このコンストラクタは、他のパッケージから呼び出せないように、
124         * パッケージプライベートにしておきます。
125         * このコンストラクタは、マスタリソースファイルを想定しています。
126         *
127         * 引数の並び順は、CLM,CODE,LNAME,SNAME,CODELVL,CODEGRP,CODE_PARAM,ROLES,SYSTEM_ID,KBSAKU,RSNAME,RLNAME,DESCRIPT
128         *
129         * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応
130         * @og.rev 4.3.8.0 (2009/08/01) rawShortLabel追加
131         * @og.rev 4.3.8.0 (2009/08/01) グループ機能とパラメータの判定、isUseFlag フラグの追加
132         * @og.rev 5.2.2.0 (2010/11/01) "_" の取り扱いの変更
133         * @og.rev 5.6.8.2 (2103/09/20) rawlongLabel追加
134         * @og.rev 6.2.0.0 (2015/02/27) description 概要説明 追加
135         * @og.rev 6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止(IE8以降ブラウザ標準)
136         *
137         * @param       clm     カラム名
138         * @param       data    規定の順番の文字列配列を格納
139         */
140        /* default */ CodeData( final String clm, final Map<String,String[]> data) {
141                column  = clm;
142
143                size = data.size();
144//              final String[] cdKeys = data.keySet().toArray( new String[size] );
145                final String[] cdKeys = data.keySet().toArray( new String[0] ); // 8.5.4.2 (2024/01/12) PMD 7.0.0 OptimizableToArrayCall 対応
146
147                code            = new String[size];
148                shortLabel      = new String[size];
149                longLabel       = new String[size];
150                codeLevel       = new String[size];
151                codeGroup       = new String[size];
152                codeParam       = new String[size];
153                roles           = new String[size];
154                roleModes       = new RoleMode[size];
155                // 8.5.4.2 (2024/01/12) PMD 7.0.0 LinguisticNaming
156//              isUseFlag       = new boolean[size];            // 5.1.9.0 (2010/08/01) サブセットフラグの追加
157                useSubset       = new boolean[size];            // 5.1.9.0 (2010/08/01) サブセットフラグの追加
158                rawShortLabel   = new String[size];
159                rawLongLabel    = new String[size];             // 5.6.8.2 (2103/09/20)
160                description             = new String[size];             // 6.2.0.0 (2015/02/27) 概要説明 追加
161
162//              // 1文字目の重複判定により、マルチセレクトの可否を判断します。
163//              final HashSet<String> set = new HashSet<>();
164//              // 6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止(IE8以降ブラウザ標準)
165//              boolean isSel = USE_MULTI_KEY_SELECT;   // 判定処理を行う。false なら判定処理も行わない。
166
167                // 5.1.9.0 (2010/08/01) コードレベル、コードグループ、パラメータ、ロールの使用可否のフラグ
168                boolean isLbl  = false;
169                boolean isPrm  = false;
170                boolean isRole = false;
171                boolean isGrp  = false;
172
173                for( int i=0; i<size; i++ ) {
174                        final String[] vals = data.get( cdKeys[i] );
175
176                        code[i] = nval2( vals[CODE],SPC );
177
178                        final String lname = nval2( vals[LNAME],SPC ) ;
179                        longLabel[i] = lname;
180
181                        // null か ゼロ文字列 : LNAME をセット
182                        // "_"                : ゼロ文字列
183                        // それ以外           : そのまま SNAME をセット
184                        shortLabel[i] = nval2( vals[SNAME]     ,lname , SPC );  // 5.2.2.0 (2010/11/01)
185
186                        codeLevel[i]  = nval2( vals[CODELVL]   , SPC ) ;
187                        codeGroup[i]  = nval2( vals[CODEGRP]   , SPC ) ;
188                        codeParam[i]  = nval2( vals[CODE_PARAM], SPC ) ;
189                        roles[i]          = nval2( vals[ROLES]     , SPC ) ;
190
191                        // 5.1.9.0 (2010/08/01) コードレベル機能と、パラメータの使用判定
192                        if( !isLbl )  { isLbl  = "0".equals(   codeLevel[i] );  }
193                        if( !isPrm )  { isPrm  = ! SPC.equals( codeParam[i] );  }
194                        if( !isRole ) { isRole = ! SPC.equals( roles[i] );              }
195                        if( !isGrp )  { isGrp  = ! SPC.equals( codeGroup[i] );  }
196
197                        roleModes[i]    = RoleMode.newInstance( roles[i] );                     // ロールモード
198                        rawShortLabel[i]= nval2( vals[RSNAME] , lname , SPC  );         // 5.2.2.0 (2010/11/01)
199                        rawLongLabel[i] = nval2( vals[RLNAME] , lname , SPC  );         // 5.6.8.2 (2013/09/20)
200                        description[i]  = nval2( vals[DESCRIPT]       , SPC  );         // 6.2.0.0 (2015/02/27)
201
202//                      // 6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止(IE8以降ブラウザ標準)
203//                      if( isSel && lname.length() > 0 ) {
204//                              isSel = set.add( lname.substring(0,1) );        // 重複時は false
205//                      }
206                }
207
208                // 8.5.4.2 (2024/01/12) PMD 7.0.0 LinguisticNaming
209//              Arrays.fill( isUseFlag,true );  // 5.1.9.0 (2010/08/01) サブセットフラグの追加
210                Arrays.fill( useSubset,true );  // 5.1.9.0 (2010/08/01) サブセットフラグの追加
211
212//              // 6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止(IE8以降ブラウザ標準)
213//              isMultiSelect = USE_MULTI_KEY_SELECT && ! isSel ;       // flag の反転に注意
214                isUseLevel    = isLbl;          // 5.1.9.0 (2010/08/01) コードレベル機能を利用するかどうか
215                isUseParam    = isPrm;          // 5.1.9.0 (2010/08/01) パラメータを利用するかどうか
216                isUseRoleMode = isRole;         // 5.1.9.0 (2010/08/01) ロールモードを利用するかどうか
217                isUseGroup    = isGrp;          // 5.1.9.0 (2010/08/01) コードグループを利用するかどうか
218        }
219
220        /**
221         * コードデータのキーを返します。
222         *
223         * @return コードデータのキー
224         */
225        public String getColumn() { return column; }
226
227        /**
228         * コードデータのキーを返します。
229         *
230         * @param       seqNo   表示順
231         *
232         * @return コードデータのキー
233         */
234        public String getCodeKey( final int seqNo ) { return code[seqNo] ; }
235
236        /**
237         * コードデータの表示名を返します。
238         *
239         * @param       seqNo   表示順
240         *
241         * @return コードデータの表示名
242         */
243        public String getLongLabel( final int seqNo ) { return longLabel[seqNo]; }
244
245        /**
246         * コードデータの短縮表示名を返します。
247         *
248         * @param seqNo 表示順
249         *
250         * @return コードデータの短縮表示名
251         */
252        public String getShortLabel( final int seqNo ) { return shortLabel[seqNo]; }
253
254        /**
255         * コード階層を返します。
256         *
257         * 通常のメニューは、階層が "1" になります。optgroup要素として使用する場合は、
258         * 階層を "0" で登録します。
259         *
260         * @param seqNo 表示順
261         *
262         * @return コード階層( "1":option要素、"0":optgroup要素 )
263         */
264        public String getCodeLevel( final int seqNo ) { return codeLevel[seqNo]; }
265
266        /**
267         * このコードが、使用できるかどうかを、返します。
268         *
269         * コードグループや、コードリストなどで、サブセットを作成する場合、
270         * プルダウンなどの選択肢は、制限しますが、レンデラーのラベルは、制限しません。
271         * これは、既存データを表示させる必要がある為です。
272         * このフラグは、選択肢を作成するときに利用します。
273         * 標準状態で作成した場合は、すべての項目が、true になっています。
274         *
275         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
276         * @og.rev 8.5.4.2 (2024/01/12) PMD 7.0.0 LinguisticNaming 対応
277         *
278         * @param       seqNo   表示順
279         *
280         * @return 使用可能な場合は、true
281         */
282//      public boolean isUse( final int seqNo ) { return isUseFlag[seqNo]; }
283        public boolean isUse( final int seqNo ) { return useSubset[seqNo]; }            // 8.5.4.2 (2024/01/12)
284
285        /**
286         * コードパラメータを返します。
287         *
288         * コードパラメータは、メニューの各要素(option要素)に設定するタグの内容を追記します。
289         * ここに記述した文字列をそのまま追記します。
290         *
291         * @param seqNo 表示順
292         *
293         * @return コードパラメータ
294         */
295        public String getCodeParam( final int seqNo ) { return codeParam[seqNo]; }
296
297        /**
298         * コードロールを取得します。
299         *
300         * @param       seqNo   表示順
301         *
302         * @return      コードロール
303         */
304        public String getRoles( final int seqNo ) { return roles[seqNo]; }
305
306        /**
307         * カラムオブジェクトのロールモードを返します。
308         *
309         * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応
310         *
311         * @param       seqNo   表示順
312         *
313         * @return カラムオブジェクトのロールモード
314         */
315        public RoleMode getRoleMode( final int seqNo ) { return roleModes[seqNo]; }
316
317        /**
318         * ロールモードを、使用しているかどうかを、返します。
319         *
320         * ロールモードを使用している場合は、ロール制御の処理が必要です。
321         * 使用している/いないを事前に判断することで、無駄な処理を削減できます。
322         *
323         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
324         *
325         * @return ロールモードを使用している場合は、true
326         */
327        public boolean useRoleMode() { return isUseRoleMode; }
328
329        /**
330         * マッチするコードデータのアドレスを返します。
331         * 一致するデータが存在しない場合は、-1 を返します。
332         *
333         * @param       key     検索するキー文字列
334         *
335         * @return コードデータのアドレス(なければ、-1)
336         */
337        public int getAddress( final String key ) {
338                int selected = -1;
339                for( int i=0; i<size; i++ ) {
340                        if( code[i].equals( key ) ) {
341                                selected = i;
342                                break;
343                        }
344                }
345                return selected;
346        }
347
348        /**
349         * コードデータの配列数を返します。
350         *
351         * @return コードデータの配列数
352         */
353        public int getSize() { return size; }
354
355//      /**
356//       * マルチ・キーセレクトを使用するかどうかを返します。
357//       * true:使用する。false:使用しない です。
358//       * 使用するにした場合でも、ラベルの先頭文字が重複しない場合は、
359//       * IEの自動選択機能によりセレクト可能なため、JavaScript は出力しません。
360//       *
361//       * @og.rev 6.9.5.0 (2018/04/23) USE_MULTI_KEY_SELECT 廃止(IE8以降ブラウザ標準)
362//       * @return  選択リストで、マルチ・キーセレクトを使用するかどうか(true:使用する)
363//       */
364//      public boolean useMultiSelect() { return isMultiSelect; }
365
366        /**
367         * コードレベル機能を利用するかどうかを返します。
368         * true:使用する。false:使用しない です。
369         * コードレベル機能を利用する場合は、optgroup タグを出力します。
370         * 設定としては、レベル 0 に指定のカラムを optgroup として出力します。
371         *
372         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
373         *
374         * @return  コードレベル機能を利用するかどうか(初期値:false:使用しない)
375         */
376        public boolean useLevel() { return isUseLevel; }
377
378        /**
379         * パラメータを利用するかどうかを返します。
380         * true:使用する。false:使用しない です。
381         * このパラメータは、class 属性として設定される値です。
382         * これを使用して、各種レイアウトなどの指定が可能です。
383         *
384         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
385         *
386         * @return  パラメータを利用するかどうか(初期値:false:使用しない)
387         */
388        public boolean useParam() { return isUseParam; }
389
390        /**
391         * コードグループを利用するかどうかを返します。
392         * true:使用する。false:使用しない です。
393         * このコードグループは、リソースの引数で設定した CSV形式に
394         * 対して、値が設定されていたかどうかを返します。
395         * これにより、不要な処理を行う必要がなくなります。
396         *
397         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
398         *
399         * @return  パラメータを利用するかどうか(初期値:false:使用しない)
400         */
401        public boolean useGroup() { return isUseGroup; }
402
403        /**
404         * オブジェクトの識別子として、詳細なコード情報を返します。
405         * キー:ラベル ・・の繰り返し文字列を返します。
406         *
407         * @og.rev 4.1.0.0 (2008/01/18) 新規追加
408         *
409         * @return  詳細なコード情報
410         */
411        public String toCodeString() {
412                final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
413                for( int i=0; i<size; i++ ) {
414                        final String key = code[i] + ":" ;
415                        if( ! longLabel[i].startsWith( key ) ) {
416                                rtn.append( key );
417                        }
418                        // 8.5.4.2 (2024/01/12) PMD 7.0.0 ConsecutiveAppendsShouldReuse 対応
419                        rtn.append( longLabel[i] )
420                                .append( ' ' );         // 6.0.2.5 (2014/10/31) char を append する。
421                }
422                return rtn.toString().trim();
423        }
424
425        /**
426         * コードデータの短縮表示名(spanタグ無し)を返します。
427         *
428         * @og.rev 4.3.8.0 (2009/08/01) 新規追加
429         *
430         * @param seqNo 表示順
431         *
432         * @return コードデータの短縮表示名(spanタグ無し)
433         */
434        public String getRawShortLabel( final int seqNo ) { return rawShortLabel[seqNo]; }
435
436        /**
437         * 未加工の名前長を返します。
438         *
439         * @og.rev 5.6.8.2 (2013/09/13) 新規追加
440         *
441         * @param seqNo 表示順
442         *
443         * @return コードデータの短縮表示名(spanタグ無し)
444         */
445        public String getRawLongLabel( final int seqNo ) { return rawLongLabel[seqNo]; }
446
447        /**
448         * 概要説明 を返します。
449         *
450         * この概要説明は、個々の コードに対する説明です。
451         * optionタグに、title属性として使用すれば、説明文になります。
452         *
453         * @og.rev 6.2.0.0 (2015/02/27) description 概要説明 追加
454         *
455         * @param seqNo 表示順
456         *
457         * @return コードデータの概要説明
458         */
459        public String getDescription( final int seqNo ) { return description[seqNo]; }
460
461        /**
462         * 指定のコードに限定された CodeData を構築して返します。
463         * このサブセットは、コードのCSV文字列に基づいて作成されます。
464         *
465         * この CodeData は、本当のサブセットではなく、プルダウンメニューなどの選択肢のリストを
466         * 制限します。これは、一覧表示(レンデラー)では、すべての既存の設定値を表示しておく
467         * 必要があるからです。そして、変更時(エディター)に、選択肢を制限します。
468         *
469         * 引数の codeCsv が、null,ゼロ文字列の場合は、自分自身を返します。(同一です)
470         *
471         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
472         * @og.rev 5.6.8.2 (2013/09/20) rawLongLabel対応
473         * @og.rev 6.2.0.0 (2015/02/27) description 概要説明 追加
474         * @og.rev 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD
475         *
476         * @param       codeCsv 指定のコードをカンマで連結されたもの
477         *
478         * @return 指定のコードに限定された CodeData
479         * @og.rtnNotNull
480         */
481        public CodeData subsetList( final String codeCsv ) {
482                if( codeCsv == null || codeCsv.isEmpty() ) {
483                        return this;
484                }
485
486                final String codes = "," + codeCsv + "," ;
487
488                final boolean[] useFlag = new boolean[size] ;           // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal
489
490                final Map<String,String[]> data = new LinkedHashMap<>();
491                for( int adrs=0; adrs<size; adrs++ ) {
492                        final String key = code[adrs] ;
493                        useFlag[adrs] = codes.indexOf( "," + key + "," ) >= 0 ; // 存在する場合のみ、true
494
495////            String[] vals = new String[MAX_LENGTH];                         // 7.2.6.0 (2020/06/30) キーワード変更
496//                      final String[] vals = new String[DATA_SIZE];            // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal
497//                      vals[CLM]               = column ;
498//                      vals[CODE]              = key ;
499//                      vals[LNAME]             = longLabel[adrs] ;
500//                      vals[SNAME]             = shortLabel[adrs] ;
501//                      vals[CODELVL]   = codeLevel[adrs] ;
502//                      vals[CODEGRP]   = codeGroup[adrs] ;
503//                      vals[CODE_PARAM]= codeParam[adrs] ;
504//                      vals[ROLES]             = roles[adrs] ;
505//                      vals[SYSTEM_ID] = null ;
506//                      vals[KBSAKU]    = null ;
507//                      vals[RSNAME]    = rawShortLabel[adrs] ;
508//                      vals[RLNAME]    = rawLongLabel[adrs] ;  // 5.6.8.2 (2013/09/20)
509//                      vals[DESCRIPT]  = description[adrs] ;   // 6.2.0.0 (2015/02/27)
510
511                        // 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD
512                        final String[] vals = makeVals( adrs );
513
514                        data.put( key,vals );
515                }
516
517                return new CodeData( column,data,useFlag );
518        }
519
520        /**
521         * 指定のgroupに所属する限定された CodeData を構築して返します。
522         * このサブセットは、コードグループのCSV文字列に指定に基づいて作成されます。
523         *
524         * この CodeData は、本当のサブセットではなく、プルダウンメニューなどの選択肢のリストを
525         * 制限します。これは、一覧表示(レンデラー)では、すべての既存の設定値を表示しておく
526         * 必要があるからです。そして、変更時(エディター)に、選択肢を制限します。
527         *
528         * 引数の group が、null,ゼロ文字列、または、内部でグループを使用していない場合は、
529         * 自分自身を返します。(同一です)
530         * 引数の group も、内部設定のグループも、CSV形式CSV で複数のグループを指定できます。
531         * この場合は、各グループのうち、どれか一つでも該当すれば、使用(true)になります。
532         *
533         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
534         * @og.rev 5.6.8.0 (2013/09/20) rawLongLabel対応
535         * @og.rev 6.2.0.0 (2015/02/27) description 概要説明 追加
536         * @og.rev 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD
537         *
538         * @param       group   指定のコードグループのCSV文字列
539         *
540         * @return 指定のgroupに所属する限定された CodeData
541         * @og.rtnNotNull
542         */
543        public CodeData subsetGroup( final String group ) {
544                if( group == null || group.isEmpty() || !isUseGroup ) {
545                        return this;
546                }
547
548                final String[] keys = group.split( "," ) ;
549
550                final boolean[] useFlag = new boolean[size] ;           // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal
551
552                final Map<String,String[]> data = new LinkedHashMap<>();
553                for( int adrs=0; adrs<size; adrs++ ) {
554                        final String cdGrp = codeGroup[adrs];
555
556                        boolean flag = SPC.equals( cdGrp );
557                        if( !flag ) {
558                                final String grpCsv = "," + cdGrp + "," ;
559                                // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
560//                              for( int i=0; i<keys.length; i++ ) {
561//                                      flag = grpCsv.indexOf( keys[i] ) >= 0 ;
562//                                      if( flag ) { break; }
563//                              }
564                                for( final String gkey : keys ) {
565                                        flag = grpCsv.indexOf( gkey ) >= 0 ;
566                                        if( flag ) { break; }
567                                }
568                        }
569
570                        useFlag[adrs] = flag;
571
572////            String[] vals = new String[MAX_LENGTH];                         // 7.2.6.0 (2020/06/30) キーワード変更
573//                      final String[] vals = new String[DATA_SIZE];            // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal
574//                      vals[CLM]               = column ;
575//                      vals[CODE]              = code[adrs] ;
576//                      vals[LNAME]             = longLabel[adrs] ;
577//                      vals[SNAME]             = shortLabel[adrs] ;
578//                      vals[CODELVL]   = codeLevel[adrs] ;
579//                      vals[CODEGRP]   = codeGroup[adrs] ;
580//                      vals[CODE_PARAM]= codeParam[adrs] ;
581//                      vals[ROLES]             = roles[adrs] ;
582//                      vals[SYSTEM_ID] = null ;
583//                      vals[KBSAKU]    = null ;
584//                      vals[RSNAME]    = rawShortLabel[adrs] ;
585//                      vals[RLNAME]    = rawLongLabel[adrs] ;  // 5.6.8.0 (2013/09/20)
586//                      vals[DESCRIPT]  = description[adrs] ;   // 6.2.0.0 (2015/02/27)
587
588                        // 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD
589                        final String[] vals = makeVals( adrs );
590
591                        data.put( code[adrs],vals );
592                }
593
594                return new CodeData( column,data,useFlag );
595        }
596
597        /**
598         * 指定のコードに限定された CodeData を構築して返します。
599         * このサブセットは、ロールの指定に基づいて作成されます。
600         *
601         * この CodeData は、本当のサブセットではなく、プルダウンメニューなどの選択肢のリストを
602         * 制限します。これは、一覧表示(レンデラー)では、すべての既存の設定値を表示しておく
603         * 必要があるからです。そして、変更時(エディター)に、選択肢を制限します。
604         *
605         * 引数の role が、null または、内部でロールを使用していない場合は、自分自身を返します。(同一です)
606         *
607         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
608         * @og.rev 5.6.8.2 (2013/09/13) rawLongLabel対応
609         * @og.rev 6.2.0.0 (2015/02/27) description 概要説明 追加
610         * @og.rev 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD
611         *
612         * @param       userRole        指定のロール(ユーザーロール)
613         *
614         * @return 指定のコードに限定された CodeData
615         * @og.rtnNotNull
616         */
617        public CodeData subsetRole( final RoleMode userRole ) {
618                if( userRole == null || !isUseRoleMode ) {
619                        return this;
620                }
621
622                final boolean[] useFlag = new boolean[size] ;           // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal
623
624                final Map<String,String[]> data = new LinkedHashMap<>();
625                for( int adrs=0; adrs<size; adrs++ ) {
626                        final byte rw = userRole.getAccessBitMode( roleModes[adrs] );
627
628                        useFlag[adrs] = RoleMode.isWrite( rw ) ;                // 書き込み可能な場合のみ、true
629
630////            String[] vals = new String[MAX_LENGTH];                 // 7.2.6.0 (2020/06/30) キーワード変更
631//                      final String[] vals = new String[DATA_SIZE];    // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal
632//                      vals[CLM]               = column ;
633//                      vals[CODE]              = code[adrs] ;
634//                      vals[LNAME]             = longLabel[adrs] ;
635//                      vals[SNAME]             = shortLabel[adrs] ;
636//                      vals[CODELVL]   = codeLevel[adrs] ;
637//                      vals[CODEGRP]   = codeGroup[adrs] ;
638//                      vals[CODE_PARAM]= codeParam[adrs] ;
639//                      vals[ROLES]             = roles[adrs] ;
640//                      vals[SYSTEM_ID] = null ;
641//                      vals[KBSAKU]    = null ;
642//                      vals[RSNAME]    = rawShortLabel[adrs] ;
643//                      vals[RLNAME]    = rawLongLabel[adrs] ;
644//                      vals[DESCRIPT]  = description[adrs] ;   // 6.2.0.0 (2015/02/27)
645
646                        // 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD
647                        final String[] vals = makeVals( adrs );
648
649                        data.put( code[adrs],vals );
650                }
651
652                return new CodeData( column,data,useFlag );
653        }
654
655        /**
656         * CodeData 作成に必要な 1行分のデータを作成します。
657         *
658         * @og.rev 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD
659         *
660         * @return  1行分のデータ
661         * @og.rtnNotNull
662         */
663        private String[] makeVals( final int adrs ) {
664                final String[] vals = new String[DATA_SIZE];            // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal
665                vals[CLM]               = column ;
666                vals[CODE]              = code[adrs] ;
667                vals[LNAME]             = longLabel[adrs] ;
668                vals[SNAME]             = shortLabel[adrs] ;
669                vals[CODELVL]   = codeLevel[adrs] ;
670                vals[CODEGRP]   = codeGroup[adrs] ;
671                vals[CODE_PARAM]= codeParam[adrs] ;
672                vals[ROLES]             = roles[adrs] ;
673                vals[SYSTEM_ID] = null ;
674                vals[KBSAKU]    = null ;
675                vals[RSNAME]    = rawShortLabel[adrs] ;
676                vals[RLNAME]    = rawLongLabel[adrs] ;
677                vals[DESCRIPT]  = description[adrs] ;   // 6.2.0.0 (2015/02/27)
678
679                return vals;
680        }
681
682        /**
683         * オブジェクトの識別子として、詳細なコード情報を返します。
684         *
685         * @og.rev 4.1.0.0 (2008/01/18) メソッド修正(改行コード削除)
686         *
687         * @return  詳細なコード情報
688         * @og.rtnNotNull
689         */
690        @Override
691        public String toString() {
692                return "column = " + toCodeString() ;
693        }
694}