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 java.util.Arrays; 019import java.util.Comparator; 020import java.util.Map; 021import java.util.HashMap; 022import java.util.concurrent.ConcurrentMap; // 6.4.3.3 (2016/03/04) 023import java.util.concurrent.ConcurrentHashMap; // 6.4.3.1 (2016/02/12) refactoring 024import java.io.Serializable; 025 026import org.opengion.hayabusa.common.HybsSystemException; // 6.4.5.0 (2016/04/08) 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<String,String> 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 final String[] keys = attribute.keySet().toArray( new String[0] ); // 8.5.4.2 (2024/01/12) PMD 7.0.0 OptimizableToArrayCall 対応 088 089 for( final String key : keys ) { 090 if( key == null ) { continue; } 091 092 // 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。 093 if( key.startsWith( SLCT_KEY ) ) { 094 final String editName = attribute.get( key ); 095 if( editName == null || editName.isEmpty() ) { 096 attribute.remove( key ); // editName の存在しない EDIT_SELECTED_ キーは削除します。 097 continue; 098 } 099 100 final String guikey = key.substring( SLCT_LEN ); // "EDIT_SELECTED_" の後ろが画面ID 101 if( guikey != null && guikey.length() > 0 ) { 102 editSelMap.put( guikey , editName ); 103 } 104 } 105 106 if( key.startsWith( NAME_KEY ) ) { 107 final String editName = attribute.get( key ); 108 if( editName == null || editName.isEmpty() ) { 109 attribute.remove( key ); // editName の存在しない EDIT_NAME_ キーは削除します。 110 continue; 111 } 112 113 // "EDIT_NAME_" より後ろで、editName の頭までが、画面ID 114 // (ただし、後ろにアンダーバーが付いているので、さらに、1文字削除対象を増やす。) 115 final int last = key.lastIndexOf(editName)-1 ; 116 if( last < 0 ) { // 一致しない場合は、キーが違うから。 117 attribute.remove( key ); // editName の一致しない EDIT_NAME_ キーは削除します。 118 continue; 119 } 120 121 final String guikey = key.substring( NAME_LEN,last ); 122 if( guikey != null && guikey.length() > 0 ) { 123 final String[] editKeys = DBEditConfig.getEditKeys( guikey, editName ); 124 final String[] editVals = new String[editKeys.length]; // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal 125 for( int i=0; i<editKeys.length; i++ ) { 126 editVals[i] = attribute.get( editKeys[i] ); 127 } 128 // Map#computeIfAbsent : 戻り値は、既存の、または計算された値。追加有り、置換なし、削除なし 129 editConfigMap.computeIfAbsent( guikey , k -> new HashMap<>() ).put( editName , new DBEditConfig( editVals ) ); 130 } 131 } 132 } 133 } 134 135 /** 136 * 編集設定オブジェクトを追加します。 137 * 138 * ここでの追加はあくまでメモリ上での登録になります。 139 * 登録した内容を永続的に登録する場合は、別途DBへの登録が必要になります。 140 * 141 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 142 * 143 * @param guikey 画面ID 144 * @param editName 編集名 145 * @param config 編集設定オブジェクト 146 */ 147 public void addEditConfig( final String guikey, final String editName, final DBEditConfig config ) { 148 // 6.4.3.1 (2016/02/12) ConcurrentMap 系は、key,val ともに not null 制限です。 149 if( guikey != null && editName != null && config != null ) { 150 151 // Map#computeIfAbsent : 戻り値は、既存の、または計算された値。追加有り、置換なし、削除なし 152 final Map<String,DBEditConfig> confMap = editConfigMap.computeIfAbsent( guikey , k -> new HashMap<>() ); 153 final DBEditConfig oldConf = confMap.get( editName ); 154 155 // 個別設定と共通設定は、同じキーでは登録できません。 156 if( oldConf != null && oldConf.isCommon() != config.isCommon() ) { 157 final String errMsg = "個別設定と共通設定は、同じキーでは登録できません。"; 158 throw new HybsSystemException( errMsg ); 159 } 160 confMap.put( editName , config ); 161 } 162 } 163 164 /** 165 * 編集設定オブジェクトを削除します。 166 * 167 * ここでの追加はあくまでメモリ上での削除になります。 168 * 登録した内容を永続的に削除する場合は、別途DBへの登録が必要になります。 169 * 170 * @og.rev 6.4.3.2 (2016/02/19) ConcurrentHashMap の同期処理を使用。 171 * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。 172 * 173 * @param guikey 画面ID 174 * @param editName 編集名 175 * 176 * @return 編集設定オブジェクト 177 */ 178 public DBEditConfig deleteEditConfig( final String guikey, final String editName ) { 179 // 6.4.3.2 (2016/02/19) ConcurrentHashMap は、key,val ともに、NOT NULL制限があります。 180 if( guikey == null || guikey.isEmpty() || 181 editName == null || editName.isEmpty() ) { return null; } 182 183 final Map<String,DBEditConfig> ecMap = editConfigMap.get( guikey ); 184 185 return ecMap == null ? null : ecMap.remove( editName ); 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 * 画面IDをキーに編集設定の一覧(配列)を返します。 211 * 返される配列は、編集名順にソートされた状態で返されます。 212 * 213 * @og.rev 6.1.0.0 (2014/12/26) refactoring: null ではなく長さが0の配列を返す。 214 * 215 * @param guikey 画面ID 216 * 217 * @return 編集設定一覧(配列) 218 * @og.rtnNotNull 219 */ 220 public DBEditConfig[] getEditConfigs( final String guikey ) { 221 if( guikey == null || guikey.isEmpty() ) { return new DBEditConfig[0] ; } // 6.1.0.0 (2014/12/26) 222 223 // 8.5.5.1 (2024/02/29) PMD 7.0.0 OnlyOneReturn メソッドには終了ポイントが 1 つだけ必要 224 final DBEditConfig[] configs; 225 226 final Map<String,DBEditConfig> map = editConfigMap.get( guikey ); 227// if( map == null ) { return new DBEditConfig[0]; } // 6.1.0.0 (2014/12/26) 228 if( map == null ) { configs = new DBEditConfig[0]; } // 6.1.0.0 (2014/12/26) 229 else { 230// final DBEditConfig[] configs = map.values().toArray( new DBEditConfig[map.size()] ); // 6.0.2.5 (2014/10/31) refactoring 231// final DBEditConfig[] configs = map.values().toArray( new DBEditConfig[0] ); // 6.0.2.5 (2014/10/31) refactoring // 8.5.4.2 (2024/01/12) PMD 7.0.0 OptimizableToArrayCall 対応 232 configs = map.values().toArray( new DBEditConfig[0] ); // 6.0.2.5 (2014/10/31) refactoring // 8.5.4.2 (2024/01/12) PMD 7.0.0 OptimizableToArrayCall 対応 233 // 6.0.2.5 (2014/10/31) findBugs対応:名前付き static 内部クラスにリファクタリングできるかもしれません。 234 Arrays.sort( configs , new EditConfigComparator() ); 235 } 236 return configs; 237 } 238 239 /** 240 * 指定の画面IDに対して選択済みの編集名を返します。 241 * 242 * @og.rev 5.3.6.0 (2011/06/01) 新規追加 243 * @og.rev 6.0.2.2 (2014/10/03) EDIT_NAME_SELECTED_ を、EDIT_SELECTED_ に変更 244 * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。 245 * 246 * @param guikey 画面ID 247 * 248 * @return 選択済み編集名 249 */ 250 public String getSelectedEdit( final String guikey ) { 251 return editSelMap.get( SLCT_KEY + guikey ); 252 } 253 254 /** 255 * DBEditConfig 比較用の Comparator 実装です。 256 * 名前なしclass から、名前あり staticクラスに格上げです。 257 * 258 * @og.rev 6.0.2.5 (2014/10/31) findBugs対応:新規追加 259 */ 260 private static final class EditConfigComparator implements Comparator<DBEditConfig>, Serializable { 261 private static final long serialVersionUID = 602520141024L ; 262 263 /** 264 * デフォルトのコンストラクタ 265 * 266 * @og.rev 8.5.5.1 (2024/02/29) デフォルトのコンストラクタは必ず用意しておく。 267 */ 268 public EditConfigComparator() { 269 super(); 270 } 271 272 /** 273 * DBEditConfig 比較メソッド 274 * インタフェース Comparable の 実装です。 275 * 276 * @og.rev 6.0.2.5 (2014/10/31) findBugs対応:新規追加 277 * 278 * @param c1 比較対象の最初のオブジェクト 279 * @param c2 比較対象の 2 番目のオブジェクト 280 * @return 最初の引数が 2 番目の引数より小さい場合は負の整数、両方が等しい場合は 0、最初の引数が 2 番目の引数より大きい場合は正の整数 281 */ 282 @Override // Comparator 283 public int compare( final DBEditConfig c1, final DBEditConfig c2 ) { 284 return c1 == null ? -1 : c1.getEditName().compareTo( c2.getEditName() ) ; 285 } 286 } 287}