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.sql.SQLException;
019import java.util.List;
020import java.util.Set;
021import java.util.ArrayList;
022import java.util.Arrays;
023import java.util.Map;
024import java.util.LinkedHashMap;                                                                         // 6.4.3.1 (2016/02/12) refactoring
025import java.util.HashMap;
026//import java.util.concurrent.ConcurrentMap;                                            // 6.4.3.3 (2016/03/04) 7.4.4.0 (2021/06/30) Delete
027//import java.util.concurrent.ConcurrentHashMap;                                        // 6.4.3.1 (2016/02/12) refactoring 7.4.4.0 (2021/06/30) Delete
028import java.util.Collections;                                                                           // 6.4.3.1 (2016/02/12) refactoring
029import java.util.Objects;                                                                                       // 8.4.2.2 (2023/03/17) ハッシュコード求め
030
031import org.opengion.fukurou.db.DBSimpleTable;
032import org.opengion.fukurou.db.DBUtil;
033import org.opengion.fukurou.db.ApplicationInfo;
034import org.opengion.fukurou.util.Cleanable;
035import org.opengion.fukurou.util.HybsEntry;
036import org.opengion.fukurou.system.DateSet;                                                     // 6.4.2.0 (2016/01/29)
037import org.opengion.fukurou.system.LogWriter;
038import org.opengion.hayabusa.common.HybsSystem;
039import org.opengion.hayabusa.common.HybsSystemException;
040import org.opengion.hayabusa.common.UserSummary;
041import org.opengion.hayabusa.db.DBEditConfig;
042import org.opengion.hayabusa.db.DBEditConfigManager;
043import static org.opengion.fukurou.system.HybsConst.CR ;                        // 6.1.0.0 (2014/12/26)
044import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.1.0.0 (2014/12/26) refactoring
045
046/**
047 * ユーザー情報の取得の為のインターフェースを実装したクラスです。
048 *
049 * ログイン時のパスワードのチェックや国名の識別ID、ポータルページのURLなど
050 * 個人情報を管理させます。
051 * 特に、画面アクセス時の権限やメールの送信、各画面にユーザー情報を表示したり、
052 * エラー時のログファイル、テンポラリディレクトリなども管理します。
053 *
054 * {@USER.XXXX} で、XXXX 部に、UserInfo オブジェクトで定義されている
055 * 属性情報を取り出すことが出来ます。
056 *
057 * 以下の値は UserInfo オブジェクトの項目から取得します。
058 * ・JNAME      ユーザー日本語名称
059 * ・ID         ユーザーID
060 * ・INFO       ユーザー情報(ユーザーID:日本語名称)
061 * ・LANG       言語
062 * ・ROLES      ロール
063 * ・IPADDRESS  IPアドレス
064 * ・LOGINTIME  ログイン時刻
065 * ・LASTACCESS 最終アクセス画面ID
066 *
067 * 以下の値はあらかじめ、動的に作成されます。
068 * ・YMD       8byte の今日のシステム日付
069 * ・YMDH    14byte の今日のシステム日時
070 *
071 * それ以外は、外部より設定された値です。
072 * 従来は、USER.IDNO はUSER.ID が5Byte以上の時のみ先頭1文字を除いたユーザーIDとして
073 * オブジェクト項目からの取得でしたが、現在は初期値として設定してあります。
074 * 外部より再設定可能になっています。
075 *
076 * @og.group リソース管理
077 *
078 * @version  4.0
079 * @author   Kazuhiko Hasegawa
080 * @since    JDK5.0,
081 */
082public class UserInfo implements UserSummary , Cleanable {
083        private static final long serialVersionUID = 568120130913L ;    // 5.6.8.1 (2013/09/13)
084
085        // ユーザーリソースのキー指定読み込みのクエリー
086        // 7.4.4.0 (2021/06/30) Delete
087        //private static final String QUERY_PARAM = HybsSystem.sys( "USER_PARAMETER_SQL" );
088
089        /** 5.6.8.1 (2013/09/13) 最終リクエスト情報のユーザー永続化情報(GE20)へのセーブに使用するキーの接頭語 */
090        private static final String LAST_REQUEST_DATA_SUFIX = "LAST_REQUEST_" ;
091
092        /** アクセス統計テーブル(GE15)への接続先を、リソースの接続先より取得します。 */
093        private final String DBID = HybsSystem.sys( "RESOURCE_DBID" );
094
095        //private static final String YOYAKU = "|JNAME|ID|INFO|LANG|ROLES|IPADDRESS|LOGINTIME|LASTACCESS|YMD|YMDH|" ;
096        private static final String YOYAKU = "|JNAME|ID|INFO|LANG|ROLES|IPADDRESS|LOGINTIME|LASTACCESS|YMD|YMDH|LASTGAMENNM" ; // 4.4.0.1 (2009/08/08)
097
098        // 8.5.4.2 (2024/01/12) PMD 7.0.0 AvoidDuplicateLiterals 対応
099        private static final String C_YMD  = "yyyyMMdd" ;                               // 8.5.4.2 (2024/01/12) PMD 7.0.0 AvoidDuplicateLiterals 対応
100        private static final String C_YMDH = "yyyyMMddHHmmss" ;         // 8.5.4.2 (2024/01/12) PMD 7.0.0 AvoidDuplicateLiterals 対応
101
102        private final boolean useAccessTable = HybsSystem.sysBool( "USE_ACCESS_TOKEI_TABLE" );
103
104        private final String    userID  ;
105        private       String    lang    ;       // 5.1.4.0 (2010/03/01) lang を書き換え可能とする。
106        private final String    jname   ;
107        private final String    roles   ;
108        // private final String droles  ; // 4.4.0.0 (2009/08/02) データロール対応 7.4.4.0 (2021/06/30) Delete
109        private final String    ipAddress       ;
110        private final long              loginTime       ;
111        /** 6.4.3.1 (2016/02/12) val=null を登録しているため、単純に、ConcurrentHashMap に置き換えできない。 */
112        private final Map<String,String>        attriMap  ;
113        private final RoleMode  roleMode ;              // ロールズとモードを管理するオブジェクト
114        //private final DataRole        dataRole ;              // データロールを管理するオブジェクト 7.4.4.0 (2021/06/30) Delete
115
116        private final int               hcode           ;                               // 6.4.1.1 (2016/01/16) PMD refactoring. Field hashcode has the same name as a method
117        /** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。 */
118        private final Map<String,GUIInfo>       guiMap = Collections.synchronizedMap( new LinkedHashMap<>() );                          // 6.4.3.1 (2016/02/12)
119        private           long          usedTime        ;                               // 4.0.0 (2005/01/31)
120        /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */
121        //private final ConcurrentMap<String,String>    paramMap = new ConcurrentHashMap<>();                                                   // 6.4.3.3 (2016/03/04) 7.4.4.0 (2021/06/30) Delete
122        private final Object    guiLock         = new Object();
123        private final String    systemId        ;
124        /** 6.4.3.1 (2016/02/12) 作成元のMapを、変更不可能なビューを返すようにするため、 ConcurrentHashMap に置き換え不要。 */
125        private Map<String,FavoriteGUIData> favoriteGuiMap      ;       // 4.1.1.0 (2008/01/22)
126        private Set<String> forbidAddrSet       ;                               // 5.2.0.0 (2010/09/01)
127        private final DBEditConfigManager editMgr ;                                                             // 6.0.2.2 (2014/10/03)
128
129        /** 6.4.3.1 (2016/02/12) val=null を登録しているため、単純に、ConcurrentHashMap に置き換えできない。 */
130        private final Map<String,String>        lastRequestMap = new HashMap<>();       // 5.6.8.1 (2013/09/13)
131
132        /** コネクションにアプリケーション情報を追記するかどうか指定 */
133        public static final boolean USE_DB_APPLICATION_INFO  = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;
134
135        /** 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定 */
136        private final ApplicationInfo appInfo;
137
138        /** ユーザー永続化情報(GE20)テーブル 読み込み用SQL */
139        // 4.3.4.0 (2008/12/01) ROLE='*'も検索できるようにする
140        // 5.3.6.0 (2011/06/01) USERID='*'も検索できるようにする
141        private static final String QUERY_GE20  = "select PARAM_ID,PARAM from GE20"
142                                                                                        +       " where SYSTEM_ID = ? and USERID in ( ?, '*' )"
143                                                                                        +       " and ROLES in ( ?, '*' ) and FGJ = '1'"
144                                                                                        +       " order by USERID,ROLES";
145
146        /** 4.3.4.0 (2008/12/01) ユーザー永続化情報(GE20)にセーブ時に存在チェックを行うためのSQL */
147        // 4.3.4.4 (2009/01/01) private static を付加
148        private static final String QUERY_GE20_KEY      = "select KBSET from GE20"
149                                                                                        +       " where SYSTEM_ID = ? and USERID = ?"
150                                                                                        +       " and ROLES = ? and PARAM_ID = ? and FGJ = '1'";
151
152        /** 5.2.3.0 (2010/12/01) アクセス履歴管理 */
153        private GUIInfo lastGuiInfo     ;
154
155        /** saveGUIAccessInfo() メソッドでしか使用しない、定数宣言 */
156        private static final int C_SYSTEM_ID            = 0 ;
157        private static final int C_USERID                       = 1 ;
158        private static final int C_USERADRS                     = 2 ;
159        private static final int C_HOSTADRS                     = 3 ;
160        private static final int C_GUIKEY                       = 4 ;
161        private static final int C_DYLOGIN                      = 5 ;
162        private static final int C_DYLOGOUT                     = 6 ;
163        private static final int C_USED_TIME            = 7 ;
164        private static final int C_CNT_ACCESS           = 8 ;
165        private static final int C_CNT_ERROR            = 9 ;
166        private static final int C_CNT_READ                     = 10 ;
167        private static final int C_CNT_WRITE            = 11 ;
168        private static final int C_TM_TOTAL_QUERY       = 12 ;
169        private static final int C_TM_MAX_QUERY         = 13 ;
170        private static final int C_MAX_QUERY            = 14 ;
171        private static final int C_FGJ                          = 15 ;
172        private static final int C_DYSET                        = 16;
173        private static final int C_DYUPD                        = 17;
174        private static final int C_USRSET                       = 18;
175        private static final int C_USRUPD                       = 19;
176        private static final int C_PGUPD                        = 20;
177
178        /** ユーザー永続化情報(GE20)設定でしか使用しない変数の宣言 */
179        private static final int C_GE20_SYSTEM_ID       = 0;
180        private static final int C_GE20_USERID          = 1;
181        private static final int C_GE20_ROLES           = 2;
182        private static final int C_GE20_PARAM_ID        = 3;
183        private static final int C_GE20_PARAM           = 4;
184        private static final int C_GE20_KBSET           = 5;
185        private static final int C_GE20_FGJ                     = 6;
186        private static final int C_GE20_DYSET           = 7;
187        private static final int C_GE20_DYUPD           = 8;
188        private static final int C_GE20_USRSET          = 9;
189        private static final int C_GE20_USRUPD          = 10;
190        private static final int C_GE20_PGUPD           = 11;
191
192        private static final int GE20_KBSET_READONLY    = 1;
193        private static final int GE20_KBSET_WRITABLE    = 2;
194
195        /** ロールは全て*で登録する。アプリケーションから動的に登録される値を、
196                ロール単位設定しても、ロール変更時に整合性が合わない可能性大なので、
197                UserInfoで設定する場合は、全てのロールで有効とする。
198         */
199        private static final String GE20_ROLES = "*";
200
201        /**
202         * コンストラクター
203         *
204         * @og.rev 3.0.0.1 (2003/02/14) ユーザー毎のエンコード指定方法を廃止します。
205         * @og.rev 3.1.3.0 (2003/04/10) ユーザー情報から、エンコード情報を削除する。
206         * @og.rev 3.4.0.3 (2003/09/10) "root","manager","admin" のロールを、すべて root 権限を与える。
207         * @og.rev 3.8.5.3 (2006/06/30) USE_USER_IDNO_C_SAPLESS を判定条件に加える。
208         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定
209         * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応
210         * @og.rev 4.4.0.0 (2009/08/02) データロール対応
211         * @og.rev 5.3.6.0 (2011/06/01) ユーザー永続化情報(GE20)の読み込みをUserInfoFactoryから移動
212         * @og.rev 6.0.2.2 (2014/10/03) DBEditConfigManager をここで作成する。
213         * @og.rev 7.4.4.0 (2021/06/30) openGionV8事前準備(DataRole.java廃止、GE16廃止)
214         * @og.rev 8.4.2.2 (2023/03/17) ハッシュコード求めに、java.util.Objects#hash を使用します。
215         *
216         * @param       userID          ユーザー
217         * @param       lang            言語
218         * @param       jname           日本語名称
219         * @param       roles           ロール
220         * @param       systemId        システムID
221         * @param       ipAddress       IPアドレス
222         * @param   appInfo             アプリ情報オブジェクト
223         */
224        public UserInfo( final String userID            ,
225                                         final String lang                      ,
226                                         final String jname                     ,
227                                         final String roles                     ,
228        //                               final String droles            , // 4.4.0.0 (2009/08/02) 7.4.4.0 (2021/06/30) Delete
229                                         final String systemId          ,
230                                         final String ipAddress         ,
231                                         final ApplicationInfo appInfo  ) {
232                this.userID             = userID        ;
233                this.lang               = lang          ;
234                this.jname              = jname         ;
235                this.roles              = roles         ;
236        //      this.droles             = droles        ; // 4.4.0.0 (2009/08/02) 7.4.4.0 (2021/06/30) Delete
237                this.systemId   = systemId      ;
238                this.roleMode   = RoleMode.newInstance( roles );        // 4.3.0.0 (2008/07/04) ロールモード
239        //      this.dataRole   = DataRole.newInstance( droles, systemId, appInfo ); // 4.4.0.0 (2009/08/02) 7.4.4.0 (2021/06/30) Delete
240                this.ipAddress  = ipAddress     ;
241                this.appInfo    = appInfo       ;
242                loginTime               = System.currentTimeMillis();
243                usedTime                = loginTime;
244                attriMap                = new HashMap<>();
245
246                // 3.5.6.0 (2004/06/18) hashCode を計算しておきます。
247                // 8.4.2.2 (2023/03/17) ハッシュコード求めに、java.util.Objects#hash を使用します。
248//              hcode = (int)(loginTime^(loginTime>>>32)) ;
249                // 2.0.0 (2024/01/12) PMD 7.0.0 UnnecessaryBoxing
250//              hcode = Objects.hash( userID, Long.valueOf( loginTime ) );
251                hcode = Objects.hash( userID, loginTime );
252
253                // 3.8.1.2 (2005/12/19) USER.IDNO をAttributeにセットする。
254                // 3.8.5.3 (2006/06/30) USE_USER_IDNO_C_SAPLESS を判定条件に加える。
255                final boolean IDNO_C_SAPLESS = HybsSystem.sysBool( "USE_USER_IDNO_C_SAPLESS" );         // 6.4.2.1 (2016/02/05) PMD refactoring. Useless parentheses.
256                final String idno = userID.length() > 5 && IDNO_C_SAPLESS ? userID.substring(1) : userID ;
257                attriMap.put( "IDNO",idno ) ;                           // コンストラクタ内なので、同期処理は入れていません。
258
259                // ユーザーパラメータなどの初期設定を行います。
260                // 7.4.4.0 (2021/06/30) Delete
261        //      initLoad() ;
262
263                // 5.3.6.0 (2011/06/01) ユーザー永続化情報(GE20)からDBに保存されたUserInfo情報を読み出します。
264                dbLoad();
265
266                // 5.3.6.0 (2011/06/01) Edit情報の一覧を作成します。
267                editMgr = new DBEditConfigManager( attriMap );                  // 6.0.2.2 (2014/10/03) 作成方法変更
268        }
269
270        /**
271         * ユーザーパラメータを取得します。
272         * ユーザーパラメーターは、通常、GE16 テーブルより取得します。
273        // * 取得するSQL文は、SystemData の USER_PARAMETER_SQL に記述しておきます。
274         * ユーザーパラメータに、値が存在しない場合は、システムリソースより
275         * 取得します。
276         *
277         * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
278         * @og.rev 7.4.4.0 (2021/06/30) openGionV8事前準備(GE16廃止)
279         *
280         * @param       key     パラメータキー
281         *
282         * @return      パラメータ値(ユーザーパラメータになければ、システムリソースより取得
283         */
284        public String getParameter( final String key ) {
285                String val = null;
286                // 8.5.4.2 (2024/01/12) PMD 7.0.0 CollapsibleIfStatements
287//              if( key != null ) {
288//                      // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
289//      //                      val = paramMap.get( key );                                                                              // 7.4.4.0 (2021/06/30) Delete
290//                      if( val == null ) { val = HybsSystem.sys( key ); }
291                if( key != null && val == null ) {
292                        // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
293        //                      val = paramMap.get( key );                                                                              // 7.4.4.0 (2021/06/30) Delete
294                        val = HybsSystem.sys( key );
295                }
296                return val;
297        }
298
299        /**
300         * ユーザーログイン時刻を取得します。
301         *
302         * @return      ログイン時刻
303         */
304        @Override       // UserSummary
305        public long getLoginTime() {
306                return loginTime;
307        }
308
309        /**
310         * ユーザーのログインIPアドレスを取得します。
311         *
312         * @return      IPアドレス
313         *
314         */
315        @Override       // UserSummary
316        public String getIPAddress() {
317                return ipAddress;
318        }
319
320        /**
321         * ユーザーを取得します。
322         *
323         * @return      ユーザー
324         *
325         */
326        @Override       // UserSummary
327        public String getUserID() {
328                return userID;
329        }
330
331        /**
332         * ユーザー情報ロケール(言語)を取得します。
333         *
334         * @return      ロケール(言語)
335         */
336        @Override       // UserSummary
337        public String getLang() {
338                return lang ;
339        }
340
341        /**
342         * ユーザー情報ロケール(言語)をセットします。
343         *
344         * @og.rev 5.1.4.0 (2010/03/01) lang を書き換え可能とする。
345         *
346         * @param newLang       ロケール(言語)
347         */
348        public void setLang( final String newLang ) {
349                lang = newLang ;
350        }
351
352        /**
353         * ユーザー情報 名称(日本語)を取得します。
354         *
355         * @return      名称(日本語)
356         */
357        @Override       // UserSummary
358        public String getJname() {
359                return jname ;
360        }
361
362        /**
363         * ユーザー情報 ロール(役割)を取得します。
364         *
365         * @return      ロール(役割)
366         */
367        @Override       // UserSummary
368        public String getRoles() {
369                return roles ;
370        }
371
372        /**
373         * ロールモード情報を取得します。
374         *
375         * @og.rev 4.3.0.0 (2008/07/04) 新規追加
376         *
377         * @return      ロールモード情報
378         */
379        public RoleMode getRoleMode() {
380                return roleMode ;
381        }
382
383        /**
384         * オブジェクトの識別子として、ユーザー情報を返します。
385         *
386         * @return  ユーザー情報
387         * @og.rtnNotNull
388         */
389        @Override       // UserSummary
390        public String getInfo() {
391                final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE )
392                        .append( userID ).append( " : " )
393                        .append( jname  ).append( CR );
394                return rtn.toString();
395        }
396
397//      /**
398//       * DBEditConfigManagerオブジェクトを返します。
399//       *
400//       * ここでは、内部オブジェクトそのものを返します。
401//       *
402//       * @og.rev 6.4.5.0 (2016/04/08) 新規追加。UserInfo オブジェクトから、出来るだけEditConfig関係の処理を除外します。
403//       * @og.rev 6.9.2.1 (2018/03/12) DBEditConfigManagerを直接取り出す処理を、廃止します。
404//       *
405//       * @return  DBEditConfigManagerオブジェクト
406//       */
407//      public DBEditConfigManager getEditConfigManager() {
408//              return editMgr;
409//      }
410
411        /**
412         * UserInfoの属性文字列を登録します。
413         *
414         * 予約文字(JNAME,ID,INFO,LANG,ROLES,IPADDRESS,LOGINTIME,LASTACCESS,YMD,YMDH,LASTGAMENNM)を
415         * 登録しようとした場合は、エラーにします。
416         *
417         * ※ 属性文字列キーが不正の場合、HybsSystemException が、throw されます。
418         *
419         * @param       key     キー
420         * @param       value   値
421         * @param       save    ユーザー永続化情報(GE20)に情報を保存するか
422         */
423        public void setAttribute( final String key,final String value, final boolean save ) {
424                setAttribute( key, value, save, false );
425        }
426
427        /**
428         * UserInfoの属性文字列を登録します。
429         *
430         * 予約文字(JNAME,ID,INFO,LANG,ROLES,IPADDRESS,LOGINTIME,LASTACCESS,YMD,YMDH,LASTGAMENNM)を
431         * 登録しようとした場合は、エラーにします。
432         *
433         * ※ 属性文字列キーが不正の場合、HybsSystemException が、throw されます。
434         *
435         * @og.rev 3.5.6.0 (2004/06/18) synchronized をattriMap に行います。
436         * @og.rev 4.3.4.0 (2008/12/01) ユーザー永続化情報(GE20)へ登録するかのフラグを追加
437         * @og.rev 5.3.6.0 (2011/06/01) ユーザー永続化情報(GE20)へ登録時に全ユーザー公開するかのフラグを追加
438         * @og.rev 5.6.8.1 (2013/09/13) 値が null、またはゼロ文字列の場合、処理しません。
439         * @og.rev 5.7.2.2 (2014/01/24) 値が null、またはゼロ文字列の場合でも処理します。(5.6.8.1 以前に戻します)
440         *
441         * @param       key     キー
442         * @param       value   値
443         * @param       save    ユーザー永続化情報(GE20)に情報を保存するか
444         * @param       common  ユーザー永続化情報(GE20)に保存した情報を全ユーザー公開するか
445         */
446        private void setAttribute( final String key,final String value, final boolean save, final boolean common ) {
447                if( key != null && YOYAKU.indexOf( "|" + key + "|" ) < 0 ) {
448                        // 5.6.8.1 (2013/09/13) 値が null、またはゼロ文字列の場合、処理しません。
449                        // 5.7.2.2 (2014/01/24) 値が null、またはゼロ文字列の場合でも処理します。(5.6.8.1 以前に戻します)
450                        synchronized( attriMap ) {
451                                attriMap.put( key,value ) ;
452                        }
453
454                        // 4.3.4.0 (2008/12/01) 追加
455                        if( save ) {
456                                savePermanently( key ,value, common );
457                        }
458                }
459                else {
460                        final String errMsg = "属性文字列キーが不正です。 key=[" + key + "]"
461                                                + CR
462                                                + "null または予約語(" + YOYAKU + ") は指定できません。";
463                        throw new HybsSystemException( errMsg );
464                }
465        }
466
467        /**
468         * UserInfoの属性文字列を取得します。
469         *
470         * 以下の値は UserInfo オブジェクトの項目から取得します。
471         * <pre>
472         * ・JNAME      ユーザー日本語名称
473         * ・ID         ユーザーID
474         * ・IDNO       (初期値)USER.ID が5Byte以上の時のみ先頭1文字を除いたユーザーID
475         * ・INFO       ユーザー情報(ユーザーID:日本語名称)
476         * ・LANG       言語
477         * ・ROLES      ロール
478         * ・IPADDRESS  IPアドレス
479         * ・LOGINTIME  ログイン時刻
480         * ・LASTACCESS 最終アクセス画面ID
481         * ・LASTGAMENNM 最終アクセス画面名
482         *
483         * 以下の値はあらかじめ、動的に作成されます。
484         * ・YMD       8byte の今日のシステム日付
485         * ・YMDH    14byte の今日のシステム日時
486         * </pre>
487         *
488         * それ以外は、外部より設定された値です。
489         *
490         * @og.rev 2.1.0.2 (2002/11/07) USER.IDNO の返す値をUSER.ID が5Byte以上の時のみ、
491         * 先頭1文字を除いた値を返す様に変更。それ以外は、USER.IDを返す。
492         *
493         * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応  ENCODE 追加
494         * @og.rev 3.1.3.0 (2003/04/10) ユーザー情報から、エンコード情報を削除する。
495         * @og.rev 3.5.4.2 (2003/12/15) ENAME,MAILTO、MAILUSERID、MAILPASSWD、GROUP、PROJECTを削除する。
496         * @og.rev 3.5.6.0 (2004/06/18) synchronized をattriMap に行います。
497         * @og.rev 3.6.0.0 (2004/09/17) PASSWD を削除する。
498         * @og.rev 3.8.1.2 (2005/12/19) USER.IDNO を削除する。(外部設定可能にするため)
499         * @og.rev 3.8.7.0 (2006/12/15) ApplicationInfoオブジェクトから最終アクセス画面を取得
500         * @og.rev 4.4.0.0 (2009/08/02) データロール属性対応
501         * @og.rev 4.4.0.1 (2009/08/08) LASTGAMENNM追加
502         * @og.rev 6.4.1.1 (2016/01/16) PMD refactoring. Position literals first in String comparisons for EqualsIgnoreCase.
503         * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。
504         * @og.rev 7.4.4.0 (2021/06/30) openGionV8事前準備(DataRole.java廃止)
505         *
506         * @param       key     キー
507         *
508         * @return      UserInfoの属性文字列
509         */
510        @Override       // UserSummary
511        public String getAttribute( final String key ) {
512                final String rtn ;
513
514                if( key == null ) { rtn = null; }
515                else {
516                        if(      "JNAME"                .equalsIgnoreCase( key ) ) { rtn = jname; }
517                        else if( "ID"                   .equalsIgnoreCase( key ) ) { rtn = userID; }
518                        else if( "INFO"                 .equalsIgnoreCase( key ) ) { rtn = getInfo(); }
519                        else if( "LANG"                 .equalsIgnoreCase( key ) ) { rtn = lang; }
520                        else if( "ROLE"                 .equalsIgnoreCase( key ) ) { rtn = roles; }
521                        else if( "ROLES"                .equalsIgnoreCase( key ) ) { rtn = roles; }
522        //              else if( "DROLES"               .equalsIgnoreCase( key ) ) { rtn = droles; } // 4.4.0.0 (2009/08/02) 7.4.4.0 (2021/06/30) Delete
523                        else if( "IPADDRESS"    .equalsIgnoreCase( key ) ) { rtn = ipAddress; }
524                        else if( "LOGINTIME"    .equalsIgnoreCase( key ) ) { rtn = HybsSystem.getDate( loginTime ); }
525                        else if( "YMD"                  .equalsIgnoreCase( key ) ) { rtn = DateSet.getDate( C_YMD ); }                  // 6.4.2.0 (2016/01/29) 8.5.4.2 (2024/01/12) PMD 7.0.0 AvoidDuplicateLiterals 対応
526                        else if( "YMDH"                 .equalsIgnoreCase( key ) ) { rtn = DateSet.getDate( C_YMDH ); }                 // 6.4.2.0 (2016/01/29) 8.5.4.2 (2024/01/12) PMD 7.0.0 AvoidDuplicateLiterals 対応
527                        else if( "LASTACCESS"   .equalsIgnoreCase( key ) ) { rtn = getGamenId(); }
528                        else if( "LASTGAMENNM"  .equalsIgnoreCase( key ) ) { rtn = getGamenName(); }
529                        else {
530                                synchronized( attriMap ) {
531                                        rtn = attriMap.get( key ) ;
532                                }
533                        }
534                }
535
536                return rtn ;
537        }
538
539        /**
540         * ApplicationInfo から、画面ID を取得します。
541         * ApplicationInfoが null の場合は、null を返します。
542         *
543         * @og.rev 6.4.1.1 (2016/01/16) 新規追加
544         *
545         * @return      画面ID(ApplicationInfo#getGamenId())
546         */
547        private String getGamenId() {
548                return appInfo == null ? null : appInfo.getGamenId();
549        }
550
551        /**
552         * GUIInfo から、画面名 を取得します。
553         * GUIInfo がない場合、または、GUIInfo の取り出しも元の、画面ID がない、
554         * さらに、画面ID の取出し元の ApplicationInfoが null の場合は、null を返します。
555         *
556         * @og.rev 6.4.1.1 (2016/01/16) 新規追加
557         *
558         * @return      画面名(GUIInfo#getName())
559         */
560        private String getGamenName() {
561                final GUIInfo guiInfo = getGUIInfo( getGamenId() );             // 引数 null 対応済み
562                return guiInfo == null ? null : guiInfo.getName();
563        }
564
565        /**
566         * UserInfoの属性文字列の内部情報を返します。
567         * この内部情報の中には、UserInfo 自身の管理情報も含めます。
568         * 独自管理キーは、JNAME,ID,IDNO,INFO,LANG,ROLES,IPADDRESS,LOGINTIME,LASTACCESS,LASTGAMENNM です。
569         *
570         * それ以外は、外部より設定された値です。
571         *
572         * @og.rev 4.0.0.0 (2004/12/31) 新規作成
573         * @og.rev 4.4.0.1 (2009/08/08) LASTGAMENNM追加
574         *
575         * @return 属性文字列のHybsEntryオブジェクト配列
576         * @og.rtnNotNull
577         */
578        public HybsEntry[] getEntrys() {
579                final List<HybsEntry> list = new ArrayList<>();
580
581                list.add( new HybsEntry( "JNAME"                , getAttribute( "JNAME"         ) ,"ユーザー日本語名称" ) );
582                list.add( new HybsEntry( "ID"                   , getAttribute( "ID"            ) ,"ユーザーID" ) );
583                list.add( new HybsEntry( "IDNO"                 , getAttribute( "IDNO"          ) ,"USER.ID が5Byte以上の時のみ先頭1文字を除いたユーザーID" ) );
584                list.add( new HybsEntry( "INFO"                 , getAttribute( "INFO"          ) ,"ユーザー情報(ユーザーID:日本語名称)" ) );
585                list.add( new HybsEntry( "LANG"                 , getAttribute( "LANG"          ) ,"言語" ) );
586                list.add( new HybsEntry( "ROLES"                , getAttribute( "ROLES"         ) ,"ロールズ" ) );
587                list.add( new HybsEntry( "IPADDRESS"    , getAttribute( "IPADDRESS" ) ,"IPアドレス" ) );
588                list.add( new HybsEntry( "LOGINTIME"    , getAttribute( "LOGINTIME" ) ,"ログイン時刻" ) );
589                list.add( new HybsEntry( "LASTACCESS"   , getAttribute( "LASTACCESS" ) ,"最終アクセス画面ID" ) );
590                list.add( new HybsEntry( "LASTGAMENNM"  , getAttribute( "LASTGAMENNM") ,"最終アクセス画面名" ) ); // 4.4.0.1 (2009/08/08)
591                list.add( new HybsEntry( "YMD"                  , getAttribute( "YMD"           ) ," 8byte の今日のシステム日付" ) );
592                list.add( new HybsEntry( "YMDH"                 , getAttribute( "YMDH"          ) ,"14byte の今日のシステム日時" ) );
593
594                synchronized( attriMap ) {
595//                      final String[] keys = attriMap.keySet().toArray( new String[attriMap.size()] );
596                        final String[] keys = attriMap.keySet().toArray( new String[0] );       // 8.5.4.2 (2024/01/12) PMD 7.0.0 OptimizableToArrayCall 対応
597                        Arrays.sort( keys );
598                        // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
599//                      for( int i=0; i<keys.length; i++ ) {
600//                              list.add( new HybsEntry( keys[i],getAttribute( keys[i] ) ) );
601//                      }
602                        for( final String key : keys ) {
603                                list.add( new HybsEntry( key,getAttribute( key ) ) );
604                        }
605                }
606//              return list.toArray( new HybsEntry[list.size()] );
607                return list.toArray( new HybsEntry[0] );        // 8.5.4.2 (2024/01/12) PMD 7.0.0 OptimizableToArrayCall 対応
608        }
609
610        /**
611         * UserInfoの属性文字列を削除します。
612         *
613         * @param       key     キー
614         * @param       save    ユーザー永続化情報(GE20)から情報を削除するか
615         */
616        public void removeAttribute( final String key, final boolean save ) {
617                removeAttribute( key, save, false );
618        }
619
620        /**
621         * UserInfoの属性文字列を削除します。
622         *
623         * @og.rev 3.5.6.0 (2004/06/18) synchronized をattriMap に行います。
624         * @og.rev 5.3.6.0 (2011/06/01) ユーザー永続化情報(GE20)から削除するかのフラグを追加
625         *
626         * @param       key     キー
627         * @param       save    ユーザー永続化情報(GE20)から情報を削除するか
628         * @param       common  ユーザー永続化情報(GE20)から情報削除時、全ユーザー公開情報を削除するか
629         */
630        private void removeAttribute( final String key, final boolean save, final boolean common ) {
631                synchronized( attriMap ) {
632                        attriMap.remove( key ) ;
633                }
634
635                if( save ) {
636                        deletePermanently( key, common );
637                }
638        }
639
640        /**
641         * ユーザー個別の画面オブジェクトのマップをセットします。
642         *
643         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定
644         * @og.rev 4.0.0.0 (2005/01/31) 新規追加
645         * @og.rev 4.1.1.0 (2008/01/29) 画面の格上げとお気に入りマップ作成はクラスUserAccessTableに依頼
646         * @og.rev 5.2.0.0 (2010/09/01) アクセス禁止アドレスによる不正アクセス防止機能追加
647         * @og.rev 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います
648         *
649         * @param       newGuiMap                       画面オブジェクトのマップ
650         * @param       newForbidAddrSet        アクセス禁止アドレスセット
651         */
652        public void setGUIMap( final Map<String,GUIInfo> newGuiMap, final Set<String> newForbidAddrSet ) {
653                if( newGuiMap != null ) {
654                        synchronized( guiLock ) {
655                                guiMap.clear();                                                 // 6.4.3.1 (2016/02/12)
656                                guiMap.putAll( newGuiMap );                             // 6.4.3.1 (2016/02/12)
657                                forbidAddrSet  = newForbidAddrSet;
658                                favoriteGuiMap = UserAccessTable.makeAccessDB( guiMap,systemId,userID,lang );
659                        }
660                }
661        }
662
663        /**
664         * ユーザー個別の画面オブジェクトを取得します。
665         * アクセスできない画面IDが指定されたときは、null が返ります。
666         *
667         * @og.rev 4.0.0.0 (2005/01/31) 新規追加
668         * @og.rev 5.2.0.0 (2010/09/01) guiMap の null 判定を追加
669         * @og.rev 6.4.1.1 (2016/01/16) 引数の gamenId が、null の場合は、null を返すように変更。
670         * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
671         *
672         * @param       gamenId 画面ID
673         *
674         * @return      画面オブジェクト
675         */
676        public GUIInfo getGUIInfo( final String gamenId ) {
677                return gamenId == null ? null : guiMap.get( gamenId );
678        }
679
680        /**
681         * ユーザー個別の画面オブジェクトのマップを取得します。
682         *
683         * @og.rev 4.0.0.0 (2005/01/31) 新規追加
684         * @og.rev 5.2.0.0 (2010/09/01) guiMap の null 判定を追加
685         * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
686         *
687         * @return      画面オブジェクトの配列
688         */
689        public GUIInfo[] getGUIInfos() {
690//              return guiMap.values().toArray( new GUIInfo[guiMap.size()] ) ;
691                return guiMap.values().toArray( new GUIInfo[0] ) ;      // 8.5.4.2 (2024/01/12) PMD 7.0.0 OptimizableToArrayCall 対応
692        }
693
694        /**
695         * アクセスが許可されているアドレスかどうかをチェックします。
696         *
697         * チェックの方法は、ブラックリスト方式です。
698         * 画面リソースに登録された一覧の内、そのユーザーが許可されていないアドレスに
699         * 対してのみfalseが返ります。
700         * 画面リソースに登録されていないアドレスや、アドレスにURLの区切り文字(/)が
701         * 含まれている場合はチェックされません。(trueが返ります)
702         *
703         * @og.rev 5.2.0.0 (2010/09/01) 新規追加
704         *
705         * @param addr チェック対象のアドレス
706         *
707         * @return アクセスが許可されているアドレスかどうか
708         */
709        public boolean isValidAddr( final String addr ) {
710                synchronized( guiLock ) {
711                        return forbidAddrSet == null || !forbidAddrSet.contains( addr ) ;
712                }
713        }
714
715        /**
716         * ユーザー個別のお気に入り画面オブジェクトのマップを取得します。
717         *
718         * @og.rev 4.1.1.0 (2008/01/31) 新規追加
719         * @og.rev 6.4.3.1 (2016/02/12) Collections.unmodifiableMap( Map&lt;? extends K,? extends V&gt; ) で作成された変更不可のMapを返します。
720         *
721         * @return      お気に入り画面オブジェクトのマップ
722         */
723        public Map<String,FavoriteGUIData> getFavoriteMap() {
724                return favoriteGuiMap;
725        }
726
727        /**
728         * 画面オブジェクトのマップがセット済みかどうかを取得します。
729         *
730         * @og.rev 4.0.0.0 (2005/01/31) 新規追加
731         * @og.rev 6.4.3.1 (2016/02/12) isInfoSet 廃止。
732         *
733         * @return 画面オブジェクトのマップがセット済みかどうか(true:セット済み / false:未セット)
734         */
735        public boolean isGUIInfoSet() {
736                return !guiMap.isEmpty();                       // 6.4.3.1 (2016/02/12)
737        }
738
739        /**
740         * 指定のユーザーロールに対する最終的なアクセス条件を取得します。
741         * アクセス条件は、複数あるユーザーロールの中で、最大のアクセス条件を算出します。
742         * 例えば、AAA(-r)|BBB(-w)|CCC(mr) の3つのロール/モードが設定されている場合、
743         * ユーザーが、AAA だけの場合は、-r ですが、AAA|BBB を持っている場合は、-w になります。
744         * さらに、BBB|CCC と持っている場合は、(-w:書き込み許可)と(mr:メニューから読取許可)の
745         * 権限により、mw:メニューからの書き込み許可が与えられます。
746         * モード指定がある場合は、AND演算になります。
747         * 例えば、AAA(-r)|BBB(-w)|CCC(mr) と BBB|CCC(-r) の場合、(-r)+(-w)+(mr)*(-r)=-w に
748         * なります。ロールは、OR ですが、モードは、同一ロールでのAND になります。
749         * 実際には、メニュー表示の可否は、ポップアップ系によく用いられますので、上記のような
750         * 許可が実際にあるかどうかは不明ですが、すべてのモードのOR条件での結合になります。
751         *
752         * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応
753         *
754         * @param       other   ロールモード
755         *
756         * @return アクセスビット
757         */
758        public byte getAccessBitMode( final RoleMode other ) {
759                return roleMode.getAccessBitMode( other );
760        }
761
762        /**
763         * このユーザーの権限で、指定のロールが許可されているかどうかを判定します。
764         *
765         * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応
766         * @og.rev 4.3.0.1 (2008/08/11) ロールチェック時の引数間違い、是正
767         * @og.rev 6.3.6.1 (2015/08/28) '_' を、null と同等に扱います(すべて許可と同じ)
768         *
769         * @param       role    チェックを行うロール
770         *
771         * @return      アクセスできる(true)/出来ない(false)
772         */
773        public boolean isAccess( final String role ) {
774                // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
775                return role == null || role.isEmpty() || role.charAt(0) == '_'
776                                || roleMode.getAccessBitMode( RoleMode.newInstance( role ) ) > 0 ;              // 4.3.0.1 (2008/08/11)
777        }
778
779        /**
780         * 初期化(クリア)します(org.opengion.fukurou.util.Cleanable の実装)。
781         * 画面オブジェクトのマップをクリアし、セット済みフラグを未セットに設定します。
782         * システムリソースの USE_ACCESS_TOKEI_TABLE が true の場合は、
783         * 画面アクセス状況を、アクセス統計テーブル(GE15)に書き込みます。
784        // * ユーザー単位のパラメータは、システムリソースの USER_PARAMETER_SQL で
785        // * 定義された値を検索して、取り込みます。
786         *
787         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定
788         * @og.rev 4.0.0.0 (2005/01/31) 新規追加
789         * @og.rev 5.6.8.1 (2013/09/13) lastRequestMap を ユーザー永続化情報(GE20) に書き込みます。
790         * @og.rev 6.4.3.1 (2016/02/12) isInfoSet 廃止。
791         * @og.rev 7.4.4.0 (2021/06/30) openGionV8事前準備(GE16廃止)
792         */
793        public void clear() {
794                if( useAccessTable && isGUIInfoSet() ) { saveGUIAccessInfo(); }         // 6.4.3.1 (2016/02/12) isInfoSet 廃止
795        //      initLoad() ;                                                                                                                    // 7.4.4.0 (2021/06/30) Delete
796
797                saveLastRequestValues();        // 5.6.8.1 (2013/09/13) lastRequestMap を ユーザー永続化情報(GE20) に書き込みます。
798        }
799
800        // /**
801        // * ユーザーパラメータを取得します。
802        // * 画面オブジェクトのマップをクリアし、セット済みフラグを未セットに設定します。
803        // * ユーザー単位のパラメータは、システムリソースの USER_PARAMETER_SQL で
804        // * 定義された値を検索して、取り込みます。
805        // *
806        // * @og.rev 4.0.0.0 (2005/01/31) 新規追加
807        // * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
808        // * @og.rev 7.4.4.0 (2021/06/30) openGionV8事前準備(GE16廃止)
809        // */
810        // private void initLoad() {
811        //      // ユーザーパラメータの取得
812        //      if( QUERY_PARAM != null && QUERY_PARAM.length() > 0 ) {
813        //              final String[] args = new String[] { systemId,userID };
814        //              // 画面ID,操作,プログラムID
815        //              if( appInfo != null ) {
816        //                      // 画面ID,操作,プログラムID
817        //                      appInfo.setModuleInfo( "UserInfo",null,"initLoad" );
818        //              }
819        //              final String[][] vals = DBUtil.dbExecute( QUERY_PARAM,args,appInfo,DBID );
820
821        //              // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
822        //                      paramMap.clear();
823        //                      for( int i=0; i<vals.length; i++ ) {
824        //                              final String key = vals[i][0];
825        //                              final String val = vals[i][1];
826        //                              // 6.4.3.1 (2016/02/12) ConcurrentMap 系は、key,val ともに not null 制限です。
827        //                              if( key != null && val != null && !val.isEmpty() ) {            // 元の条件 val.isEmpty() も加味しておきます。
828        //                                      paramMap.put( key,val );
829        //                              }
830        //                      }
831        //      }
832        // }
833
834        /**
835         * ユーザー永続化情報(GE20)からDBに保存されたUserInfoのパラメーターを取得します。
836         *
837         * ここでは、キーの先頭が、LAST_REQUEST_DATA_SUFIX(="LAST_REQUEST_")文字列が、
838         * 付いている物だけ lastRequestMap マップに設定します。(分けて管理します)
839         *
840         * @og.rev 5.3.6.0 (2011/06/01) 新規追加
841         * @og.rev 5.6.8.1 (2013/09/13) setAttribute メソッドではなく、直接 Mapに登録します。
842         * @og.rev 5.7.2.2 (2014/01/24) 値が null、またはゼロ文字列の場合でも処理します。(5.6.8.1 以前に戻します)
843         *
844         * ※ コンストラクタのみで呼ばれるため、synchronized は入れていません。
845         * @see         #LAST_REQUEST_DATA_SUFIX
846         */
847        private void dbLoad() {
848                // ユーザー永続化情報(GE20)テーブル読み込み
849                // 8.5.4.2 (2024/01/12) PMD 7.0.0 UseShortArrayInitializer
850//              final String[] argsGe20 = new String[] { systemId,userID,roles };
851                final String[] argsGe20 = { systemId,userID,roles };
852                final String[][] valsGe20 = DBUtil.dbExecute( QUERY_GE20,argsGe20,appInfo,DBID );
853
854                // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
855//              for( int i=0; i<valsGe20.length; i++ ) {
856                for( final String[] clms : valsGe20 ) {
857                        // 4.3.4.0 (2008/12/01) ユーザー永続化情報(GE20)から読み込んでいるので、当然保存しない
858//                      final String key = valsGe20[i][0];
859//                      final String val = valsGe20[i][1];
860                        final String key = clms[0];
861                        final String val = clms[1];
862                        if( key != null && key.length() > 0 ) {
863                                if( key.startsWith( LAST_REQUEST_DATA_SUFIX ) ) {
864                                        // val が null かどうかは問わない
865                                        lastRequestMap.put( key.substring( LAST_REQUEST_DATA_SUFIX.length() ) , val );
866                                }
867                                else {
868                                        // 5.7.2.2 (2014/01/24) 値が null、またはゼロ文字列の場合でも処理します。(5.6.8.1 以前に戻します)
869                                        attriMap.put( key,val ) ;
870                                }
871                        }
872                }
873        }
874
875        /**
876         * 画面ID、編集名より編集設定オブジェクトを返します。
877         * また、ここで指定された編集名がこの画面での選択済み編集として登録されます。
878         *
879         * @og.rev 5.3.6.0 (2011/06/01) 新規追加
880         * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。
881         *
882         * @param guikey 画面ID
883         * @param editName 編集名
884         *
885         * @return 編集設定オブジェクト
886         */
887        public DBEditConfig getEditConfig( final String guikey, final String editName ) {
888                if( editName != null ) {
889                        final String selEditName = getAttribute( "EDIT_SELECTED_" + guikey );
890                        if( !editName.equals( selEditName ) ) {
891                                setAttribute( "EDIT_SELECTED_" + guikey, editName, true );
892                        }
893                }
894        //      else {
895        //              setSelectedEdit( guikey, null );
896        //      }
897                return editMgr.getEditConfig( guikey, editName );
898        }
899
900        /**
901         * 編集設定オブジェクトの配列を返します。
902         *
903         * DBEditConfigManagerを直接返していましたが、それを廃止します。
904         *
905         * @og.rev 6.9.2.1 (2018/03/12) DBEditConfigManagerを直接取り出す処理を、廃止します。
906         *
907         * @param guikey 画面ID
908         * @return  編集設定オブジェクトの配列
909         */
910        public DBEditConfig[] getEditConfigs( final String guikey ) {
911                return editMgr.getEditConfigs( guikey );
912        }
913
914        /**
915         * 指定の画面ID、編集名で編集設定オブジェクトを追加します。
916         * 既に登録されている場合は、既存の編集情報を更新します。
917         *
918         * ※ 廃止予定ですが、対応が間に合わないため、暫定的に残しています。
919         *
920         * @og.rev 5.3.6.0 (2011/06/01) 新規追加
921         * @og.rev 5.7.1.2 (2013/12/20) msg ⇒ errMsg 変更
922         * @og.rev 6.0.2.2 (2014/10/03) getEditKeys(String,String) を、DBEditConfig ⇒ DBEditConfigManager 変更
923         * @og.rev 6.3.9.1 (2015/11/27) getEditKeys(String,String) は、DBEditConfigManager ⇒ DBEditConfig へ移動。
924         * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。廃止
925         *
926         * @param guikey 画面ID
927         * @param editName 編集名
928         * @param config 編集設定オブジェクト
929         */
930        public void addEditConfig( final String guikey, final String editName, final DBEditConfig config ) {
931                if( config != null ) {
932                        editMgr.addEditConfig( guikey, editName, config );
933
934                        final boolean isCommon = config.isCommon();
935                        config.forEach( guikey
936                                                , (key,val) -> {
937                                                                if( val != null && val.length() > 0 ) {
938                                                                        setAttribute( key, val, true, isCommon );
939                                                                }
940                                                                else {
941                                                                        removeAttribute( key, true, isCommon );
942                                                                }
943                                                        } );
944                }
945        }
946
947        /**
948         * 指定の画面ID、編集名の編集設定を削除します。
949         *
950         * ※ 廃止予定ですが、対応が間に合わないため、暫定的に残しています。
951         *
952         * @og.rev 5.3.6.0 (2011/06/01) 新規追加
953         * @og.rev 5.7.1.2 (2013/12/20) msg ⇒ errMsg 変更
954         * @og.rev 6.0.2.2 (2014/10/03) getEditKeys( String, String ) を、DBEditConfig ⇒ DBEditConfigManager 変更
955         * @og.rev 6.3.9.1 (2015/11/27) getEditKeys(String,String) は、DBEditConfigManager ⇒ DBEditConfig へ移動。
956         * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。廃止
957         *
958         * @param guikey 画面ID
959         * @param editName 編集名
960         */
961        public void deleteEditConfig( final String guikey, final String editName ) {
962                final DBEditConfig config = editMgr.deleteEditConfig( guikey, editName );
963                if( config != null ) {
964                        final boolean isCommon = config.isCommon();
965        //              final String[] editKeys = DBEditConfig.getEditKeys( guikey, editName );                 // 6.3.9.1 (2015/11/27) メソッド移動
966        //              // 編集設定が存在しない場合エラー。
967        //              if( !isExistValue( editKeys[0], ( isCommon ? "*" : userID ), "*" ) ) {
968        //                      final String errMsg = "編集設定が存在しません。";
969        //                      throw new HybsSystemException( errMsg );        // 5.7.1.2 (2013/12/20) msg ⇒ errMsg 変更
970        //              }
971
972                        config.forEach( guikey , (key,val) -> removeAttribute( key, true, isCommon ) );
973
974        //              for( int i=0; i<editKeys.length; i++ ) {
975        //                      removeAttribute( editKeys[i], true, isCommon );
976        //              }
977                        removeAttribute( "EDIT_SELECTED_"      + guikey, true, isCommon );              // 6.0.2.2 (2014/10/03) 初期値用のキーも削除
978                        removeAttribute( "EDIT_NAME_SELECTED_" + guikey, true, isCommon );              // 6.0.2.2 (2014/10/03) 昔のキーは強制削除
979                }
980
981        //      if( editName != null ) {
982        //              String selEditName = getSelectedEdit( guikey );
983        //              if( !editName.equals( selEditName ) ) {
984        //                      setSelectedEdit( guikey, null );
985        //              }
986        //      }
987        }
988
989        /**
990         * 指定の画面IDに対して選択済みの編集名を返します。
991         *
992         * @og.rev 5.3.6.0 (2011/06/01) 新規追加
993         * @og.rev 6.0.2.2 (2014/10/03) EDIT_NAME_SELECTED_ を、EDIT_SELECTED_ に変更
994         * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。廃止
995         *
996         * @param guikey 画面ID
997         *
998         * @return 選択済み編集名
999         */
1000        public String getSelectedEdit( final String guikey ) {
1001                return getAttribute( "EDIT_SELECTED_" + guikey );
1002        }
1003
1004        /**
1005         * 最後に使用されたリクエスト変数の値を、Mapを読み取って登録します。
1006         *
1007         * 読み取り対象は、先に lastRequestMap に登録済みのキーだけです。
1008         * そのため、{&#064;LAST.XXXX} で値を要求されたときに、キーが
1009         * 登録されていない場合は、キーだけ(値 nullで)登録しておきます。
1010         *
1011         * @og.rev 5.6.8.1 (2013/09/13) 新規追加
1012         *
1013         * @param reqMap リクエスト変数のMap
1014         */
1015        public void setLastRequestMap( final Map<String,String[]> reqMap ) {
1016                if( reqMap != null ) {
1017                        synchronized( lastRequestMap ) {
1018                                for( final String key : lastRequestMap.keySet() ) {
1019                                        if( key != null ) {                                                                     // 6.4.3.3 (2016/03/04)
1020                                                final String[] vals = reqMap.get( key );
1021                                                if( vals != null ) {
1022                                                        String val = null;
1023                                                        // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
1024//                                                      for( int i=0; i<vals.length; i++ ) {
1025//                                                              val = vals[i];
1026                                                        for( final String tmp : vals ) {
1027                                                                val = tmp;
1028                                                                if( ! "0".equals( val ) ) { break; }    // チェックボックス対応
1029                                                        }
1030                                                        lastRequestMap.put( key, val );                         // val は、null もあり得る。
1031                                                }
1032                                        }
1033                                }
1034                        }
1035                }
1036        }
1037
1038        /**
1039         * 最後に使用されたリクエスト変数の値を、設定します。
1040         *
1041         * この処理は、{&#064;LAST.XXXX} は、リクエスト値があれば、それが優先的に
1042         * 使われます。
1043         *
1044         * @og.rev 5.6.8.1 (2013/09/13) 新規追加
1045         *
1046         * @param  key リクエストキー
1047         * @param  val 設定値
1048         */
1049        public void setLastRequestValue( final String key,final String val ) {
1050                if( key != null && key.length() > 0) {
1051                        synchronized( lastRequestMap ) {
1052                                lastRequestMap.put( key, val );
1053                        }
1054                }
1055        }
1056
1057        /**
1058         * 最後に使用されたリクエスト変数の値を、取得します。
1059         *
1060         * 画面で簡素に使用できるように、少し特殊な処理を行います。
1061         * query 画面で {&#064;LAST.XXXX} を呼ぶと、lastRequestMap にキーがなければ、
1062         * キーだけ先に追加します。あれば、値を取得するだけです。
1063         * そして、result画面で command="NEW" の場合のみ、リクエスト情報のMapから、
1064         * lastRequestMap に持っているキーで(NULLでない場合は)上書きセットします。
1065         * キャッシュ量を減らすことと、処理の対象キーを減らす意味を持っています。
1066         *
1067         * @og.rev 5.6.8.1 (2013/09/13) 新規追加
1068         *
1069         * @param  key リクエストキー
1070         * @return 設定値
1071         */
1072        public String getLastRequestValue( final String key ) {
1073                String rtn = null;
1074                if( key != null && key.length() > 0) {
1075                        synchronized( lastRequestMap ) {
1076                                if( lastRequestMap.containsKey( key ) ) {       // キーを持っているかどうかを判定
1077                                        rtn = lastRequestMap.get( key );
1078                                }
1079                                else {
1080                                        lastRequestMap.put( key, null );                // キーだけ登録しておく。
1081                                }
1082                        }
1083                }
1084                return rtn ;
1085        }
1086
1087        /**
1088         * lastRequestMap を ユーザー永続化情報(GE20) に書き込みます。
1089         *
1090         * clear() 処理が実行された場合に、まとめて ユーザー永続化情報(GE20) に書き込みます。
1091         * タイミング的には、saveGUIAccessInfo() メソッドと同じですが、saveGUIAccessInfo() は、
1092         * 書き込む条件( useAccessTable &amp;&amp; isInfoSet ) があります。
1093         * セーブする時には、他の属性と区別するため、接頭語 LAST_REQUEST_DATA_SUFIX(="LAST_REQUEST_") を
1094         * キーに付けて渡します。
1095         *
1096         * 読み取りは、dbLoad() で、attriMap と同じタイミングで、コンストラクタで、行います。
1097         *
1098         * @og.rev 5.6.8.1 (2013/09/13) 新規追加
1099         * @og.rev 6.3.9.0 (2015/11/06) Map.keySet() ではなく、Map.entrySet() を使う様に変更。
1100         * @og.rev 6.4.3.4 (2016/03/11) forループを、forEach メソッドに置き換えます。
1101         *
1102         * @see         #clear()
1103         * @see         #dbLoad()
1104         */
1105        private void saveLastRequestValues() {
1106                int cnt = 0;
1107                synchronized( lastRequestMap ) {
1108                        // 6.3.9.0 (2015/11/06) Map.keySet() ではなく、Map.entrySet() を使う様に変更。
1109                        // 6.4.3.4 (2016/03/11) forループを、forEach メソッドに置き換えます。
1110                        lastRequestMap.forEach( (key,val) -> savePermanently( LAST_REQUEST_DATA_SUFIX + key , val , false ) );
1111
1112                        cnt = lastRequestMap.size();
1113                }
1114                System.out.println( "  [" + userID + "] 最終リクエスト情報({@LAST.XXXX})を、(GE20)に、[" + cnt + "]件、登録しました。" );
1115        }
1116
1117        /**
1118         * アクセスログ取得の為、ApplicationInfoオブジェクトを返します。
1119         *
1120         * @og.rev 3.8.7.0 (2006/12/15) 新規追加
1121         *
1122         * @param       gamenId 実行中の画面ID
1123         * @param       prgId   実行中のプログラムID
1124         *
1125         * @return      ApplicationInfoオブジェクト
1126         */
1127        public ApplicationInfo getApplicationInfo( final String gamenId,final String prgId ) {
1128                if( appInfo != null ) {
1129                        // 画面ID,操作,プログラムID
1130                        appInfo.setModuleInfo( gamenId,null,prgId );
1131                }
1132                return appInfo;
1133        }
1134
1135        /**
1136         * 自然比較メソッド
1137         * インタフェース Comparable の 実装です。
1138         * ユーザーの順序は、ユーザーID そのものの順序であらわされます。
1139         * 同一ユーザーの場合は、ログインタイムの順番になります。
1140         *
1141         * @og.rev 5.1.8.0 (2010/07/01) UserSummary の Comparable を型設定
1142         *
1143         * @param       object  比較対象のObject
1144         *
1145         * @return      このオブジェクトが指定されたオブジェクトより小さい場合は負の整数、等しい場合はゼロ、大きい場合は正の整数
1146         */
1147        @Override       // Comparable
1148        public int compareTo( final UserSummary object ) {
1149                int test1 = userID.compareTo( object.getUserID() );
1150                if( test1 == 0 ) {
1151                        test1 = (int)( loginTime - object.getLoginTime() ) ;
1152                }
1153                return test1;
1154        }
1155
1156        /**
1157         * このオブジェクトと他のオブジェクトが等しいかどうかを示します。
1158         * インタフェース Comparable の 実装に関連して、再定義しています。
1159         * ユーザーは、ユーザーIDが等しく、かつ ログイン時刻が同一の場合に、
1160         * 等しいと判断されます。
1161         *
1162         * @param   object 比較対象の参照オブジェクト
1163         *
1164         * @return      引数に指定されたオブジェクトとこのオブジェクトが等しい場合は true、そうでない場合は false
1165         */
1166        @Override       // Object
1167        public boolean equals( final Object object ) {
1168                // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
1169                return object instanceof UserInfo
1170                                        && userID.equals( ((UserInfo)object).getUserID()  )
1171                                        && loginTime == ( ((UserInfo)object).getLoginTime() );
1172        }
1173
1174        /**
1175         * オブジェクトのハッシュコード値を返します。
1176         * このメソッドは、java.util.Hashtable によって提供されるような
1177         * ハッシュテーブルで使用するために用意されています。
1178         * equals( Object ) メソッドをオーバーライトした場合は、hashCode() メソッドも
1179         * 必ず 記述する必要があります。
1180         * ここでは、ログイン時刻(long 値)の上位 32 ビットと下位 32 ビットの排他的論理和
1181         * を求めています。
1182         * (int)(this.longValue()^(this.longValue()&gt;&gt;&gt;32))
1183         *
1184         * ※ hashCode の 同一オブジェクトには同一ハッシュコードという規則と
1185         *    発生頻度,ランダム性を考慮すれば、ログイン時刻そのもの(long)の
1186         *    ハッシュコードでも運用上は全く問題ないと考えられます。
1187         *
1188         * @og.rev 3.5.6.0 (2004/06/18) 新規追加
1189         *
1190         * @return  このオブジェクトのハッシュコード値
1191         *
1192         */
1193        @Override       // Object
1194        public int hashCode() { return hcode ; }
1195
1196        /**
1197         * オブジェクトの識別子として、詳細なユーザー情報を返します。
1198         *
1199         * @return  詳細なユーザー情報
1200         * @og.rtnNotNull
1201         */
1202        @Override       // Object
1203        public String toString() {
1204                final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE )
1205                        .append( "userID   :" ).append( userID   ).append( CR )
1206                        .append( "lang     :" ).append( lang     ).append( CR )
1207                        .append( "jname    :" ).append( jname    ).append( CR )
1208                        .append( "roles    :" ).append( roles    ).append( CR )
1209                        .append( "IPAddress:" ).append( ipAddress ).append( CR )
1210                        .append( "loginTime:" ).append( loginTime ).append( CR );
1211                return rtn.toString();
1212        }
1213
1214        /**
1215         * ユーザー個別の画面オブジェクトの明細情報をアクセス統計テーブル(GE15)に登録します。
1216         *
1217         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定
1218         * @og.rev 4.0.0.0 (2005/01/31) 新規追加
1219         * @og.rev 4.0.0.0 (2007/10/05) SQLServer 互換性の為、SUBSTRB を廃止します。
1220         * @og.rev 4.1.1.0 (2008/01/30) ユーザーアクセス画面管理テーブルに画面の最終アクセス時間を更新
1221         * @og.rev 5.0.2.0 (2009/11/01) 作成・更新日付がセットされていないバグを修正
1222         * @og.rev 5.2.3.0 (2010/12/01) 画面アクセスの履歴(順番)を管理する機能を追加
1223         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
1224         * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。
1225         * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
1226         */
1227        private void saveGUIAccessInfo() {
1228        //      if( !useAccessTable || !isInfoSet ) { return ; }
1229
1230                final GUIInfo[] infos = getGUIInfos() ;
1231                guiMap.clear();                                                 // 6.4.3.1 (2016/02/12) getGUIInfos() してから、クリアします。
1232
1233                final long crntTime = System.currentTimeMillis();
1234
1235                // 8.5.4.2 (2024/01/12) PMD 7.0.0 UseShortArrayInitializer
1236//              final String[] names = new String[] {
1237                final String[] names = {
1238                        "SYSTEM_ID","USERID","USERADRS","HOSTADRS","GUIKEY","DYLOGIN","DYLOGOUT",
1239                        "USED_TIME","CNT_ACCESS","CNT_ERROR","CNT_READ","CNT_WRITE",
1240                        "TM_TOTAL_QUERY","TM_MAX_QUERY","MAX_QUERY","FGJ","DYSET","DYUPD","USRSET","USRUPD","PGUPD"
1241                };
1242
1243                final String[] values = new String[names.length];               // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal
1244
1245                values[C_SYSTEM_ID              ] = HybsSystem.sys( "SYSTEM_ID" );
1246                values[C_USERID                 ] = userID;
1247                values[C_USERADRS               ] = ipAddress;
1248                values[C_HOSTADRS               ] = HybsSystem.sys( "HOST_ADRS" );
1249                values[C_GUIKEY                 ] = "";
1250                values[C_DYLOGIN                ] = DateSet.getDate( loginTime,C_YMDH );                        // 6.4.2.0 (2016/01/29) 8.5.4.2 (2024/01/12) PMD 7.0.0 AvoidDuplicateLiterals 対応
1251                values[C_DYLOGOUT               ] = DateSet.getDate( C_YMDH );                                          // 6.4.2.0 (2016/01/29) 8.5.4.2 (2024/01/12) PMD 7.0.0 AvoidDuplicateLiterals 対応
1252                values[C_USED_TIME              ] = String.valueOf( Math.round( (crntTime-usedTime) / 1000.0d ) );      // 秒に変換
1253                values[C_CNT_ACCESS             ] = "0";
1254                values[C_CNT_ERROR              ] = "0";
1255                values[C_CNT_READ               ] = "0";
1256                values[C_CNT_WRITE              ] = "0";
1257                values[C_TM_TOTAL_QUERY ] = "0";
1258                values[C_TM_MAX_QUERY   ] = "0";
1259                values[C_MAX_QUERY              ] = "";
1260                values[C_FGJ                    ] = "1";
1261                values[C_DYSET                  ] = DateSet.getDate( C_YMDH );                                          // 6.4.2.0 (2016/01/29) 8.5.4.2 (2024/01/12) PMD 7.0.0 AvoidDuplicateLiterals 対応
1262                values[C_DYUPD                  ] = DateSet.getDate( C_YMDH );                                          // 6.4.2.0 (2016/01/29) 8.5.4.2 (2024/01/12) PMD 7.0.0 AvoidDuplicateLiterals 対応
1263                values[C_USRSET                 ] = "userInfo";
1264                values[C_USRUPD                 ] = "userInfo";
1265                values[C_PGUPD                  ] = "userInfo";
1266
1267                usedTime = crntTime ;
1268
1269                final DBSimpleTable dbTable = new DBSimpleTable( names );
1270                // 画面ID,操作,プログラムID
1271                getApplicationInfo( "UserInfo","saveGUI" );
1272                dbTable.setApplicationInfo( appInfo );  // 3.8.7.0 (2006/12/15)
1273                dbTable.setConnectionID( DBID );                // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応
1274                dbTable.setTable( "GE15" );
1275                // 4.0.0.0 (2007/10/05) SQLServer 互換性の為、CLOB化します。
1276        //      dbTable.addConstrain( names[C_MAX_QUERY],"SUBSTRB(?,1,4000)" );
1277
1278                boolean okFlag = false;
1279                try {
1280                        dbTable.startInsert();
1281
1282                        // UserInfo に関する情報の登録
1283                        dbTable.execute( values );
1284
1285                        // GUIInfo に関する情報の登録
1286                        if( infos != null ) {
1287                                values[C_USED_TIME] = "0";      // USED_TIME をクリアしておきます。
1288                                final String logoutTime = DateSet.getDate( C_YMDH );                                    // 6.4.2.0 (2016/01/29) 8.5.4.2 (2024/01/12) PMD 7.0.0 AvoidDuplicateLiterals 対応
1289                                // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
1290//                              for( int i=0; i<infos.length; i++ ) {
1291//                                      final GUIAccessCount access = infos[i].getGUIAccessCount();
1292                                for( final GUIInfo guiInfo : infos ) {
1293                                        final GUIAccessCount access = guiInfo.getGUIAccessCount();
1294                                        final int cnt = access.getAccessCount();
1295                                        if( cnt > 0 ) {
1296                                                values[C_GUIKEY                 ] = access.getKey();
1297                                                values[C_CNT_ACCESS             ] = String.valueOf( cnt );
1298                                                values[C_CNT_ERROR              ] = String.valueOf( access.getErrorCount() );
1299                                                values[C_CNT_READ               ] = String.valueOf( access.getReadCount() );
1300                                                values[C_CNT_WRITE              ] = String.valueOf( access.getWriteCount() );
1301                                                values[C_TM_TOTAL_QUERY ] = String.valueOf( access.getQueryTime() );
1302                                                values[C_TM_MAX_QUERY   ] = String.valueOf( access.getMaxQueryTime() );
1303                                                values[C_MAX_QUERY              ] = access.getMaxQuery();
1304        //                                      dbTable.addValues( values );
1305                                                dbTable.execute( values );
1306                                                // 4.1.1.0(2008/01/28)画面アクセス時間の更新
1307                                                // 5.2.3.0 (2010/12/01) 画面アクセスの履歴(順番)を管理する機能を追加
1308//                                              final String keys = infos[i].getNextGuiKeys();
1309                                                final String keys = guiInfo.getNextGuiKeys();
1310                                                UserAccessTable.updateLastAccessTime( systemId,userID,access.getKey(),logoutTime,keys );
1311                                        }
1312                                }
1313                        }
1314                        okFlag = true;
1315                }
1316                catch( final SQLException ex) {
1317                        LogWriter.log( "  [" + userID + "] アクセス統計テーブル(GE15)登録時にエラーが発生しました" );
1318                        LogWriter.log( ex.getMessage() );
1319                }
1320                finally {
1321                        final int cnt = dbTable.close( okFlag );
1322                        System.out.println( "  [" + userID + "] アクセス統計テーブル(GE15)に、[" + cnt + "]件、追加しました。" );
1323                }
1324        }
1325
1326        /**
1327         * userInfoにセットされた値/キーをDBに登録します。
1328         * 既にキーが存在している場合は、既存データを更新し、なければ追加します。
1329         *
1330         * @og.rev 5.3.6.0 (2011/06/01) 全ユーザー情報として保存できるように対応
1331         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
1332         * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。
1333         * @og.rev 6.4.5.0 (2016/04/08) DBEditConfigManager で使えるように、private → public にします(ちょっと不安)。
1334         *
1335         * @param key キー
1336         * @param value 値
1337         * @param isCommon ユーザーID='*'(全ユーザー公開)として登録するかどうか
1338         */
1339        public void savePermanently( final String key, final String value, final boolean isCommon ) {
1340
1341                // 追加変更時に共通でセットされる値を設定
1342                // 8.5.4.2 (2024/01/12) PMD 7.0.0 UseShortArrayInitializer
1343//              final String[] names = new String[] {
1344                final String[] names = {
1345                        "SYSTEM_ID","USERID","ROLES","PARAM_ID","PARAM","KBSET"
1346                        ,"FGJ","DYSET","DYUPD","USRSET","USRUPD","PGUPD"
1347                };
1348
1349                final String[] values = new String[names.length];               // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal
1350                values[C_GE20_SYSTEM_ID ] = HybsSystem.sys( "SYSTEM_ID" );
1351                values[C_GE20_USERID    ] = ( isCommon ? "*" : userID );
1352                values[C_GE20_ROLES             ] = GE20_ROLES;
1353                values[C_GE20_PARAM_ID  ] = key;
1354                values[C_GE20_PARAM             ] = value;
1355                values[C_GE20_KBSET             ] = String.valueOf( GE20_KBSET_WRITABLE );
1356                values[C_GE20_FGJ               ] = "1";
1357                values[C_GE20_DYSET             ] = DateSet.getDate( C_YMDH );                          // 6.4.2.0 (2016/01/29) 8.5.4.2 (2024/01/12) PMD 7.0.0 AvoidDuplicateLiterals 対応
1358                values[C_GE20_DYUPD             ] = DateSet.getDate( C_YMDH );                          // 6.4.2.0 (2016/01/29) 8.5.4.2 (2024/01/12) PMD 7.0.0 AvoidDuplicateLiterals 対応
1359                values[C_GE20_USRSET    ] = userID;
1360                values[C_GE20_USRUPD    ] = userID;
1361                values[C_GE20_PGUPD     ] = "UserInfo";
1362
1363                // 画面ID,操作,プログラムID
1364                getApplicationInfo( "UserInfo","registValueToDB" );
1365
1366                final DBSimpleTable dbTable = new DBSimpleTable( names );
1367                dbTable.setApplicationInfo( appInfo );  // 3.8.7.0 (2006/12/15)
1368                dbTable.setConnectionID( DBID );                // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応
1369                dbTable.setTable( "GE20" );
1370
1371                boolean okFlag = false;
1372                try {
1373                        if( isExistValue( key, isCommon ? "*" : userID, GE20_ROLES ) ) {
1374                                final String where = "SYSTEM_ID = [SYSTEM_ID] and USERID = [USERID] and ROLES = [ROLES] and PARAM_ID = [PARAM_ID] and FGJ='1'";
1375                                dbTable.setWhere( where );
1376                                dbTable.startUpdate();
1377                        }
1378                        else {
1379                                dbTable.startInsert();
1380                        }
1381                        dbTable.execute( values );
1382                        okFlag = true;
1383                }
1384                catch( final SQLException ex ) {
1385                        throw new HybsSystemException( "ユーザー永続化情報(GE20)設定時にエラーが発生しました", ex );
1386                }
1387                finally {
1388                        dbTable.close( okFlag );
1389                }
1390        }
1391
1392        /**
1393         * userInfoから削除された値/キーをDBからも削除します。
1394         *
1395         * @og.rev 5.3.6.0 (2011/06/01) 新規追加
1396         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
1397         *
1398         * @param key キー
1399         * @param isCommon ユーザーID='*'(全ユーザー公開)から削除するかどうか
1400         */
1401        private void deletePermanently( final String key, final boolean isCommon ) {
1402
1403                // 追加変更時に共通でセットされる値を設定
1404                // 8.5.4.2 (2024/01/12) PMD 7.0.0 UseShortArrayInitializer
1405//              final String[] names = new String[] { "SYSTEM_ID","USERID","ROLES","PARAM_ID" };
1406                final String[] names = { "SYSTEM_ID","USERID","ROLES","PARAM_ID" };
1407                final String[] values = new String[names.length];               // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal
1408                values[C_GE20_SYSTEM_ID ] = HybsSystem.sys( "SYSTEM_ID" );
1409                values[C_GE20_USERID    ] = ( isCommon ? "*" : userID );
1410                values[C_GE20_ROLES             ] = GE20_ROLES;
1411                values[C_GE20_PARAM_ID  ] = key;
1412
1413                // 画面ID,操作,プログラムID
1414                getApplicationInfo( "UserInfo","deleteValueFromDB" );
1415
1416                final DBSimpleTable dbTable = new DBSimpleTable( names );
1417                dbTable.setApplicationInfo( appInfo );
1418                dbTable.setConnectionID( DBID );                // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応
1419                dbTable.setTable( "GE20" );
1420
1421                boolean okFlag = false;
1422                try {
1423                        final String where = "SYSTEM_ID = [SYSTEM_ID] and USERID = [USERID] and ROLES = [ROLES] and PARAM_ID = [PARAM_ID] and FGJ='1'";
1424                        dbTable.setWhere( where );
1425                        dbTable.startDelete();
1426                        dbTable.execute( values );
1427                        okFlag = true;
1428                }
1429                catch( final SQLException ex ) {
1430                        throw new HybsSystemException( "ユーザー永続化情報(GE20)削除時にエラーが発生しました", ex );
1431                }
1432                finally {
1433                        dbTable.close( okFlag );
1434                }
1435        }
1436
1437        /**
1438         * ユーザー永続化情報(GE20)に該当のキーが存在するかをチェックします。
1439         *
1440         * @og.rev 5.3.6.0 (2011/06/01) 全ユーザー情報として保存できるように対応
1441         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
1442         *
1443         * @param key キー
1444         * @param userid ユーザーID
1445         * @param roles ロール
1446         *
1447         * @return true:存在している/false:存在していない
1448         */
1449        private boolean isExistValue( final String key, final String userid, final String roles ) {
1450                final String[] args = { HybsSystem.sys( "SYSTEM_ID" ), userid, roles, key };
1451
1452                // 画面ID,操作,プログラムID
1453                getApplicationInfo( "UserInfo","isExistValue" );
1454
1455                // 8.5.5.1 (2024/02/29) PMD 7.0.0 OnlyOneReturn メソッドには終了ポイントが 1 つだけ必要
1456                boolean flag ;
1457                final String[][] rtn = DBUtil.dbExecute( QUERY_GE20_KEY, args, appInfo, DBID ); // 5.5.5.1 (2012/08/07)
1458                if( rtn == null || rtn.length == 0 ) {
1459//                      return false;
1460                        flag = false;
1461                }
1462                else if( rtn[0].length > 0 ) {
1463                        if( String.valueOf( GE20_KBSET_READONLY ).equals( rtn[0][0] ) ) {
1464                                throw new HybsSystemException( "読み取り専用情報のため、書き込みできません" );
1465                        }
1466                        else {
1467//                              return true;
1468                                flag = true;
1469                        }
1470                }
1471                else {
1472                        throw new HybsSystemException( "ユーザー永続化情報(GE20)検索時にエラーが発生しました。" );
1473                }
1474                return flag;
1475        }
1476
1477        // /**
1478        // * 指定されたカラムキーに対応するデータの条件式を返します。
1479        // *
1480        // * @og.rev 4.4.0.0 (2009/08/02) 新規追加
1481        // * @og.rev 7.4.4.0 (2021/06/30) openGionV8事前準備(DataRole.java廃止)
1482        // *
1483        // * @param clm カラム名
1484        // *
1485        // * @return データの条件式
1486        // */
1487        // 7.4.4.0 (2021/06/30) Delete
1488        // public String getDataCondition( final String clm ) {
1489        //      return dataRole.getCondition( clm );
1490        // }
1491
1492        /**
1493         * このユーザーでアクセスされた画面オブジェクトを設定します。
1494         *
1495         * これは、画面アクセスの履歴(順番)を管理する機能に使います。
1496         *
1497         * @og.rev 5.2.3.0 (2010/12/01) 新規追加
1498         *
1499         * @param guiInfo 画面オブジェクト
1500         */
1501        public void setAccessGui( final GUIInfo guiInfo ) {
1502                if( lastGuiInfo != null && guiInfo != null ) {
1503                        lastGuiInfo.setNextGuiKey( guiInfo.getKey() );
1504                }
1505                lastGuiInfo = guiInfo ;         // 最後にアクセスした GUIInfo を設定
1506        }
1507}