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