    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.db;
    017
    018import org.opengion.hayabusa.common.HybsSystemException;                        // 6.4.5.0 (2016/04/08)
    019
    020import java.util.Arrays;
    021import java.util.Comparator;
    022import java.util.Map;
    023import java.util.HashMap;
    024import java.util.concurrent.ConcurrentMap;                                                      // 6.4.3.3 (2016/03/04)
    025import java.util.concurrent.ConcurrentHashMap;                                          // 6.4.3.1 (2016/02/12) refactoring
    026import java.io.Serializable;
    027
    028/**
    029 * ユーザー単位の編集設定情報を管理するためのクラスです。
    030 *
    031 * 画面ID+編集名をキーとして編集設定オブジェクトの
    032 * 追加、削除、参照を行います。
    033 *
    034 * @og.rev 5.3.6.0 (2011/06/01) 新規追加
    035 *
    036 * @version  5.0
    037 * @author   Hiroki Nakamura
    038 * @since    JDK6.0,
    039 */
    040public class DBEditConfigManager {
    041
    042        // 編集設定情報の管理オブジェクト(画面ID+編集名単位で管理)
    043        /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。  */
    044        private final ConcurrentMap<String,Map<String,DBEditConfig>> editConfigMap = new ConcurrentHashMap<>();
    045
    046        private static final String NAME_KEY = "EDIT_NAME_" ;                   // 6.4.5.0 (2016/04/08)
    047        private static final int    NAME_LEN = NAME_KEY.length();               // 6.4.5.0 (2016/04/08)
    048
    049        // EDIT_SELECTED_ + 画面ID で、設定される 選択中編集名を記録します。
    050        private final ConcurrentMap<String,String> editSelMap = new ConcurrentHashMap<>();
    051
    052        private static final String SLCT_KEY = "EDIT_SELECTED_" ;               // 6.4.5.0 (2016/04/08)
    053        private static final int    SLCT_LEN = SLCT_KEY.length();               // 6.4.5.0 (2016/04/08)
    054
    055        /**
    056         * デフォルトコンストラクター
    057         *
    058         * 互換性を考慮し、デフォルトコンストラクターは残しておきます。
    059         *
    060         * @og.rev 6.0.2.2 (2014/10/03) 新規追加
    061         */
    062        public DBEditConfigManager() { super(); }               // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    063
    064        /**
    065         * 引数付コンストラクター
    066         *
    067         * UserInfo の Map&lt;String,String&gt; attribute から、EDIT_NAME_ で始まるキーワードを
    068         * 取り出して、DBEditConfig オブジェクトを作成します。
    069         * attribute には、"EDIT_NAME_(画面ID)_(編集名)" というキー情報があるので、
    070         * 画面IDと編集名を分離し、DBEditConfig の各キーと再び合成して、attribute から、
    071         * 設定値を取り出します。
    072         * ただし、画面IDや、編集名 にも、アンダーバーが含まれている可能性がある為、
    073         * EDIT_NAME_(画面ID)_(編集名) の値である、編集名 を使用して、分離します。
    074         * そのキーと値の配列を元に作成された DBEditConfig オブジェクトを、内部Map に画面IDを
    075         * キーに設定します。
    076         *
    077         * 元々、UserInfo#makeEditConfigMap() で処理していた内容を、こちらに移植しました。
    078         *
    079         * @og.rev 6.0.2.2 (2014/10/03) 新規追加。DBEditConfig から、移動
    080         * @og.rev 6.3.9.1 (2015/11/27) getEditKeys(String,String) は、DBEditConfigManager ⇒ DBEditConfig へ移動。
    081         * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。
    082         *
    083         * @param attribute     UserInfo の 属性Map
    084         */
    085        public DBEditConfigManager( final Map<String,String> attribute ) {
    086                final String[] keys = attribute.keySet().toArray( new String[attribute.size()] );
    087
    088                for( final String key : keys ) {
    089                        if( key == null ) { continue; }
    090
    091                        // 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。
    092                        if( key.startsWith( SLCT_KEY ) ) {
    093                                final String editName = attribute.get( key );
    094                                if( editName == null || editName.isEmpty() ) {
    095                                        attribute.remove( key );                // editName の存在しない EDIT_SELECTED_ キーは削除します。
    096                                        continue;
    097                                }
    098
    099                                final String guikey = key.substring( SLCT_LEN );        // "EDIT_SELECTED_" の後ろが画面ID
    100                                if( guikey != null && guikey.length() > 0 ) {
    101                                        editSelMap.put( guikey , editName );
    102                                }
    103                        }
    104
    105                        if( key.startsWith( NAME_KEY ) ) {
    106                                final String editName = attribute.get( key );
    107                                if( editName == null || editName.isEmpty() ) {
    108                                        attribute.remove( key );                // editName の存在しない EDIT_NAME_ キーは削除します。
    109                                        continue;
    110                                }
    111
    112                                // "EDIT_NAME_" より後ろで、editName の頭までが、画面ID
    113                                // (ただし、後ろにアンダーバーが付いているので、さらに、1文字削除対象を増やす。)
    114                                final int last = key.lastIndexOf(editName)-1 ;
    115                                if( last < 0 ) {                                        // 一致しない場合は、キーが違うから。
    116                                        attribute.remove( key );                // editName の一致しない EDIT_NAME_ キーは削除します。
    117                                        continue;
    118                                }
    119
    120                                final String guikey = key.substring( NAME_LEN,last );
    121                                if( guikey != null && guikey.length() > 0 ) {
    122                                        final String[] editKeys = DBEditConfig.getEditKeys( guikey, editName );
    123                                        String[] editVals = new String[editKeys.length];
    124                                        for( int i=0; i<editKeys.length; i++ ) {
    125                                                editVals[i] = attribute.get( editKeys[i] );
    126                                        }
    127                                        // Map#computeIfAbsent ： 戻り値は、既存の、または計算された値。追加有り、置換なし、削除なし
    128                                        editConfigMap.computeIfAbsent( guikey , k -> new HashMap<>() ).put( editName , new DBEditConfig( editVals ) );
    129                                }
    130                        }
    131                }
    132        }
    133
    134        /**
    135         * 編集設定オブジェクトを追加します。
    136         *
    137         * ここでの追加はあくまでメモリ上での登録になります。
    138         * 登録した内容を永続的に登録する場合は、別途DBへの登録が必要になります。
    139         *
    140         * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
    141         *
    142         * @param guikey 画面ID
    143         * @param editName 編集名
    144         * @param config 編集設定オブジェクト
    145         */
    146        public void addEditConfig( final String guikey, final String editName, final DBEditConfig config ) {
    147                // 6.4.3.1 (2016/02/12) ConcurrentMap 系は、key,val ともに not null 制限です。
    148                if( guikey != null && editName != null && config != null ) {
    149
    150                        // Map#computeIfAbsent ： 戻り値は、既存の、または計算された値。追加有り、置換なし、削除なし
    151                        final Map<String,DBEditConfig> confMap = editConfigMap.computeIfAbsent( guikey , k -> new HashMap<>() );
    152                        final DBEditConfig oldConf = confMap.get( editName );
    153
    154                        // 個別設定と共通設定は、同じキーでは登録できません。
    155                        if( oldConf != null && oldConf.isCommon() != config.isCommon() ) {
    156                                final String errMsg = "個別設定と共通設定は、同じキーでは登録できません。";
    157                                throw new HybsSystemException( errMsg );
    158                        }
    159                        confMap.put( editName , config );
    160                }
    161        }
    162
    163        /**
    164         * 編集設定オブジェクトを削除します。
    165         *
    166         * ここでの追加はあくまでメモリ上での削除になります。
    167         * 登録した内容を永続的に削除する場合は、別途DBへの登録が必要になります。
    168         *
    169         * @og.rev 6.4.3.2 (2016/02/19) ConcurrentHashMap の同期処理を使用。
    170         * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。
    171         *
    172         * @param guikey 画面ID
    173         * @param editName 編集名
    174         *
    175         * @return 編集設定オブジェクト
    176         */
    177        public DBEditConfig deleteEditConfig( final String guikey, final String editName ) {
    178                // 6.4.3.2 (2016/02/19) ConcurrentHashMap は、key,val ともに、NOT NULL制限があります。
    179                if( guikey   == null || guikey.isEmpty() ||
    180                        editName == null || editName.isEmpty() ) { return null; }
    181
    182                final Map<String,DBEditConfig> ecMap = editConfigMap.get( guikey );
    183
    184                return ecMap == null ? null : ecMap.remove( editName );
    185
    186        }
    187
    188        /**
    189         * 編集設定オブジェクトを取得します。
    190         *
    191         * @og.rev 6.4.3.2 (2016/02/19) ConcurrentHashMap の同期処理を使用。
    192         * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。
    193         *
    194         * @param guikey 画面ID
    195         * @param editName 編集名
    196         *
    197         * @return 編集設定オブジェクト
    198         */
    199        public DBEditConfig getEditConfig( final String guikey, final String editName ) {
    200                // 6.4.3.2 (2016/02/19) ConcurrentHashMap は、key,val ともに、NOT NULL制限があります。
    201                if( guikey   == null || guikey.isEmpty() ||
    202                        editName == null || editName.isEmpty() ) { return null; }
    203
    204                final Map<String,DBEditConfig> ecMap = editConfigMap.get( guikey );
    205
    206                return ecMap == null ? null : ecMap.get( editName );
    207
    208        }
    209
    210        /**
    211         * 画面IDをキーに編集設定の一覧(配列)を返します。
    212         * 返される配列は、編集名順にソートされた状態で返されます。
    213         *
    214         * @og.rev 6.1.0.0 (2014/12/26) refactoring: null ではなく長さが0の配列を返す。
    215         *
    216         * @param guikey 画面ID
    217         *
    218         * @return 編集設定一覧(配列)
    219         * @og.rtnNotNull
    220         */
    221        public DBEditConfig[] getEditConfigs( final String guikey ) {
    222                if( guikey == null || guikey.isEmpty() ) { return new DBEditConfig[0] ; }       // 6.1.0.0 (2014/12/26)
    223
    224                final Map<String,DBEditConfig> map = editConfigMap.get( guikey );
    225                if( map == null ) { return new DBEditConfig[0]; }                                                       // 6.1.0.0 (2014/12/26)
    226
    227                final DBEditConfig[] configs = map.values().toArray( new DBEditConfig[map.size()] );    // 6.0.2.5 (2014/10/31) refactoring
    228                // 6.0.2.5 (2014/10/31) findBugs対応:名前付き static 内部クラスにリファクタリングできるかもしれません。
    229                Arrays.sort( configs , new EditConfigComparator() );
    230
    231                return configs;
    232        }
    233
    234        /**
    235         * 指定の画面IDに対して選択済みの編集名を返します。
    236         *
    237         * @og.rev 5.3.6.0 (2011/06/01) 新規追加
    238         * @og.rev 6.0.2.2 (2014/10/03) EDIT_NAME_SELECTED_ を、EDIT_SELECTED_ に変更
    239         * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。
    240         *
    241         * @param guikey 画面ID
    242         *
    243         * @return 選択済み編集名
    244         */
    245        public String getSelectedEdit( final String guikey ) {
    246                return editSelMap.get( SLCT_KEY + guikey );
    247        }
    248
    249        /**
    250         * DBEditConfig  比較用の Comparator 実装です。
    251         * 名前なしclass から、名前あり staticクラスに格上げです。
    252         *
    253         * @og.rev 6.0.2.5 (2014/10/31) findBugs対応:新規追加
    254         */
    255        private static final class EditConfigComparator implements Comparator<DBEditConfig>, Serializable {
    256                private static final long serialVersionUID = 602520141024L ;
    257
    258                /**
    259                 * DBEditConfig  比較メソッド
    260                 * インタフェース Comparable の 実装です。
    261                 *
    262                 * @og.rev 6.0.2.5 (2014/10/31) findBugs対応:新規追加
    263                 *
    264                 * @param c1 比較対象の最初のオブジェクト
    265                 * @param c2 比較対象の 2 番目のオブジェクト
    266                 * @return      最初の引数が 2 番目の引数より小さい場合は負の整数、両方が等しい場合は 0、最初の引数が 2 番目の引数より大きい場合は正の整数
    267                 */
    268                public int compare( final DBEditConfig c1, final DBEditConfig c2 ) {
    269                        return c1 == null ? -1 : c1.getEditName().compareTo( c2.getEditName() ) ;
    270                }
    271        }
    272}