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.html; 017 018import org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.hayabusa.db.DBTableModel; 020import org.opengion.hayabusa.db.DBColumn; 021import org.opengion.fukurou.util.StringUtil; 022import org.opengion.fukurou.util.Attributes; 023import org.opengion.fukurou.model.Formatter; 024 025import java.util.Map; 026import java.util.HashMap; 027import java.util.List; 028import java.util.ArrayList; 029import java.util.Arrays ; 030 031/** 032 * ViewMarker インターフェース の実装オブジェクトです。 033 * これを,共通のスーパークラスとして 各種表示フォーム(例:HTML表示等)に使います。 034 * 035 * このクラスは、setter/getterメソッドのデフォルト実装を提供しています。 036 * 各種表示フォームに対応したサブクラス上で, create() をオーバーライドして下さい。 037 * 038 * @og.group 画面表示 039 * 040 * @version 4.0 041 * @author Kazuhiko Hasegawa 042 * @since JDK5.0, 043 */ 044public class ViewMarker_MARKER implements ViewMarker { 045 046 private List<Attributes> markData = null; // 4.0.0 (2005/08/31) 047// private Map<Integer,int[]> formMap_c = new HashMap<Integer,int[]>(); // 3.5.6.1 (2004/06/25) 048// private Map<Integer,String[]> formMap_f = new HashMap<Integer,String[]>(); // 3.5.6.1 (2004/06/25) 049 private Map<Integer,Formatter> formMap = new HashMap<Integer,Formatter>(); 050 private DBTableModel table = null; 051 private int[] markCmlNo = null; 052 private int[] isMark = null; 053 private static final int MARK_NULL = -1; // マーカー未設定 054 private static final int MARK_TRUE = 1; // マーカー作成 055 private static final int MARK_FALSE = 0; // マーカー作成せず 056 // 3.5.2.0 (2003/10/20) 057 private String[] markKey = null; 058 private String[] markLists = null; 059 private String[] instrVals = null; // 3.8.8.1 (2007/01/06) 060 private int[] markListNo = null; 061 private boolean[] useFmtDeco = null; // 5.6.3.0 (2013/04/01) [$XXXX],[#XXXX]機能を有効にするかどうか(true:有効) 062 063 private Map<Integer,List<Integer>> clmMap = new HashMap<Integer,List<Integer>>(); // 4.0.0 (2005/08/31) 064 065 /** 066 * 内容をクリア(初期化)します。 067 * 068 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 069 * @og.rev 3.5.2.0 (2003/10/20) markLists,markListNo,markKey属性を追加 070 * @og.rev 3.5.6.1 (2004/06/25) formMap属性を追加 071 * @og.rev 3.8.8.1 (2007/01/06) instrVals属性を追加 072 * @og.rev 5.6.3.0 (2013/04/01) useFmtDeco属性を追加 073 * 074 */ 075 public void clear() { 076 markData = null; // 4.0.0 (2005/08/31) 077// formMap_c = new HashMap<Integer,int[]>(); // 3.5.6.1 (2004/06/25) 078// formMap_f = new HashMap<Integer,String[]>(); // 3.5.6.1 (2004/06/25) 079 formMap = new HashMap<Integer,Formatter>(); 080 table = null; 081 isMark = null; 082 markKey = null; 083 markLists = null; 084 instrVals = null; // 3.8.8.1 (2007/01/06) 085 markListNo = null; 086 clmMap = new HashMap<Integer,List<Integer>>(); // 4.0.0 (2005/08/31) 087 useFmtDeco = null; // 5.6.3.0 (2013/04/01) [$XXXX],[#XXXX]機能を有効にするかどうか(true:有効) 088 } 089 090 /** 091 * カラムに対するマーカーアトリビュートをセットします。 092 * 093 * @og.rev 3.1.0.0 (2003/03/20) Hashtable を使用している箇所で、非同期でも構わない箇所を、HashMap に置換え。 094 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 095 * 096 * @param attri アトリビュート 097 */ 098 public void addAttribute( final Attributes attri ) { 099 if( markData == null ) { markData = new ArrayList<Attributes>(); } 100 markData.add( attri ); 101 } 102 103 /** 104 * 内部に DBTableModel をセットします。 105 * 106 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 107 * @og.rev 3.5.2.0 (2003/10/20) markLists,markListNo,markKey属性を追加 108 * @og.rev 3.5.6.1 (2004/06/25) DBTableModel の再設定に対応。 109 * @og.rev 3.8.8.1 (2007/01/06) instrVals属性を追加 110 * @og.rev 5.6.3.0 (2013/04/01) useFmtDeco属性を追加 111 * 112 * @param tbl DBTableModelオブジェクト 113 */ 114 public void setDBTableModel( final DBTableModel tbl ) { 115 table = tbl; 116 int count = markData.size(); // 4.0.0 (2005/08/31) 117 118 isMark = new int[ count ]; 119 markKey = new String[ count ]; 120 markCmlNo = new int[ count ]; 121 markLists = new String[ count ]; 122 instrVals = new String[ count ]; 123 markListNo = new int[ count ]; 124 useFmtDeco = new boolean[ count ]; // 5.6.3.0 (2013/04/01) [$XXXX],[#XXXX]機能を有効にするかどうか(true:有効) 125 126 Arrays.fill( isMark,MARK_FALSE ); // マーカーの表示可否 127 Arrays.fill( markCmlNo,-1 ); // マーカーの可否を判断するカラム番号 128 Arrays.fill( useFmtDeco,false ); // [$XXXX],[#XXXX]機能を無効にする。(互換性のため) 129 130 for( int intKey=0; intKey<count; intKey++ ) { 131 Attributes attri = markData.get( intKey ); 132 133 String column = attri.get( "column" ); 134 int clm = table.getColumnNo( column ); 135 List<Integer> list = clmMap.get( clm ); 136 if( list == null ) { list = new ArrayList<Integer>(); } 137 list.add( intKey ); 138 clmMap.put( clm,list ); 139 140 String body = attri.get( "body" ); 141// makeFormat( intKey,body ); 142 Formatter formatter = new Formatter( table ); 143 formatter.setFormat( body ); 144 formMap.put( intKey, formatter ); 145 146 makeOnMarkFormat( intKey,attri ); 147 148 useFmtDeco[intKey] = "true".equalsIgnoreCase( attri.get( "useFormatDeco" ) ); // 5.6.3.0 (2013/04/01) 149 } 150 } 151 152 /** 153 * 指定の行列に対するマーカー文字列を返します。 154 * この値は,すでにマーカー文字列処理されている為, RendererValue で 155 * 変換する必要はありません。 156 * 引数の value はそのカラムの値として利用されます。この値は、修飾済みの 157 * 値を与えることが可能です。 158 * 159 * @og.rev 3.5.6.1 (2004/06/25) formMap属性を使用します。 160 * @og.rev 3.8.8.1 (2007/01/06) instrVals属性を追加 161 * @og.rev 5.3.9.0 (2011/09/01) カラム名の先頭に'$'を付加した場合に、URLEncodeされた値を返すように対応 162 * @og.rev 5.6.3.0 (2013/04/01) useFmtDeco属性を追加([$XXXX],[#XXXX]機能を有効にするかどうか) 163 * 164 * @param row 指定の行 165 * @param clm 指定の列 166 * @param value カラムの値 167 * 168 * @return row行,colum列 のマーカー文字列 169 */ 170 public String getMarkerString( final int row,final int clm,final String value ) { 171 int intKey = isOnMark(row,clm) ; 172 if( intKey < 0 ) { return value; } 173 174 Formatter formatter = formMap.get( intKey ); 175 int[] clmNo = formatter.getClmNos(); 176 String[] format = formatter.getFormat(); 177 178 char[] types = formatter.getType(); 179 180// int[] clmNo = formMap_c.get( intKey ); 181// String[] format = formMap_f.get( intKey ); 182 183 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_LARGE ); 184 int j=0; 185 String val ; 186 for( ; j<clmNo.length; j++ ) { 187 if( clm == clmNo[j] ) { 188 val = value; 189 } 190 else { 191// val = table.getValue(row,clmNo[j]); 192 val = formatter.getValue(row,clmNo[j]); 193 } 194 195 // 5.6.3.0 (2013/04/01) useFmtDeco属性を追加(trueの場合は、[$XXXX],[#XXXX]機能を有効にする) 196 if( useFmtDeco[intKey] ) { 197 DBColumn dbClm = table.getDBColumn( clmNo[j] ); 198 if( types[j] == '$' ) { 199 val = dbClm.getRendererValue( row,val ); 200 } 201 else if( types[j] == '#' ) { 202 val = dbClm.getLabel(); 203 } 204 } 205 // false が以前と同じ処理(互換処理)ただし、view などのフォーマット処理とは異なる。 206 else { 207 // 5.3.9.0 (2011/09/01) カラム名の先頭に'$'を付加した場合URLEncodeされた値を返すように対応 208 if( types[j] == '$' ) { 209 val = StringUtil.urlEncode( val ); 210 } 211 } 212 213 buf.append( format[j] ); 214 buf.append( val ); 215 } 216 if( j < format.length ) { buf.append( format[j] ); } 217 String rtn = StringUtil.replace( buf.toString(),"{I}",String.valueOf( row ) ); 218 219 // 3.8.8.1 (2007/01/06) instrVals属性を追加 220 if( instrVals[intKey] != null ) { 221 String[] vals = StringUtil.csv2Array( instrVals[intKey],' ' ); 222 for( int i=0; i<vals.length; i++ ) { 223 String css = "<span class=\"instr" + i + "\">" + vals[i] + "</span>"; 224 rtn = StringUtil.replace( rtn,vals[i],css ); 225 } 226 } 227 return rtn ; 228 } 229 230 /** 231 * マーカーフォーマットを作成します。 232 * 233 * @og.rev 3.5.6.1 (2004/06/25) formMap属性を使用します。 234 * @og.rev 3.8.8.1 (2007/01/06) countTokensの方法を見直します。 235 * 236 * @param intKey カラムキーのカラム番号 237 * @param fmt マーカーフォーマット 238 */ 239// private void makeFormat( final int intKey,final String fmt ) { 240// int start = 0; 241// int index = fmt.indexOf( '[' ); 242// List<String> clmNoList = new ArrayList<String>(); 243// List<String> formatList = new ArrayList<String>(); 244// while( index >= 0 ) { 245// int end = fmt.indexOf( ']',index ); 246// if( end < 0 ) { 247// String errMsg = "[ と ] との対応関係がずれています。" + HybsSystem.CR 248// + "format=[" + fmt + "] : index=" + index ; 249// throw new HybsSystemException( errMsg ); 250// } 251// 252// // [ より前方の文字列は、formatList へ 253// if( index > 0 ) { formatList.add( fmt.substring( start,index ) ); } 254// else { formatList.add( "" ); } 255// 256// // [XXXX] の XXXX部分を処理 257// clmNoList.add( fmt.substring( index+1,end ) ); 258// 259// start = end+1 ; 260// index = fmt.indexOf( '[',start ); 261// } 262// // ] の後方部分は、formatList へ 263// formatList.add( fmt.substring( start ) ); 264// 265// String[] format = formatList.toArray( new String[formatList.size()] ); 266// String[] clmNm = clmNoList.toArray( new String[clmNoList.size()] ); 267// 268// int size = clmNm.length ; 269// int[] clmNo = new int[ size ]; 270// for( int i=0; i<size; i++ ) { 271// clmNo[i] = table.getColumnNo( clmNm[i] ); 272// } 273// 274// formMap_c.put( intKey, clmNo ); 275// formMap_f.put( intKey, format ); 276// } 277 278 /** 279 * マーカーを作成する/作成しないの指定カラム番号を求めます。 280 * また、int[列番号] isMark を初期化します。 281 * 282 * @og.rev 3.5.2.0 (2003/10/20) markLists,markListNo,markKey属性を追加 283 * @og.rev 3.8.8.1 (2007/01/06) instrVals属性を追加 284 * 285 * @param intKey カラムキーの番号 286 * @param attri アトリビュート 287 */ 288 private void makeOnMarkFormat( final int intKey,final Attributes attri ) { 289 String onMark = attri.get( "onMark" ); 290 String markList = attri.get( "markList" ); 291 instrVals[intKey] = attri.get( "instrVals" ); // 3.8.8.1 (2007/01/06) 292 293 // 3.5.6.0 (2004/06/18) nullポインタの参照外しバグの対応 294 // このロジックで値が設定済みであれば、以下の処理は不要である。 295 isMark[intKey] = MARK_NULL; 296 if( onMark == null || onMark.length() == 0 || 297 markList == null || markList.length() == 0 ) { 298 isMark[intKey] = MARK_FALSE; 299 return ; // 3.5.6.0 (2004/06/18) 300 } 301 else if( onMark.charAt( 0 ) != '[' && markList.charAt( 0 ) != '[' ) { 302 isMark[intKey] = ( markList.indexOf( onMark ) >= 0 ) ? MARK_TRUE : MARK_FALSE; 303 return ; // 3.5.6.0 (2004/06/18) 304 } 305 306 if( onMark.charAt( 0 ) == '[' ) { 307 markCmlNo[intKey] = table.getColumnNo( onMark.substring( 1,onMark.length()-1 )); 308 } 309 else { 310 markCmlNo[intKey] = -1; 311 markKey[intKey] = onMark ; 312 } 313 314 if( markList.charAt( 0 ) == '[' ) { 315 markListNo[intKey] = table.getColumnNo( markList.substring( 1,markList.length()-1 )); 316 } 317 else { 318 markListNo[intKey] = -1; 319 markLists[intKey] = markList; 320 } 321 } 322 323 /** 324 * マーカーを作成するかどうかを判断します。 325 * int[列番号] isMark には、 未設定 FALSE TRUE の状態を持っており、 326 * 列でマーカーを作成する状態が固定の場合(例えば,onMark属性がデフォルト "true" の場合) 327 * カラムに関係なく、同じ値を返すときに、使用します。 328 * 329 * @og.rev 3.5.2.0 (2003/10/20) markLists,markListNo,markKey属性を追加 330 * @og.rev 3.5.4.0 (2003/11/25) onMark ,markList が null(またはゼロストリング)の場合は、false とする。 331 * @og.rev 4.0.0.0 (2005/08/31) 同一カラムの複数登録を許可します。 332 * 333 * @param row 列番号 334 * @param clm カラムキーの名称 335 * 336 * @return 処理するリスト番号、-1 の場合は、該当なし 337 */ 338 private int isOnMark( final int row,final int clm ) { 339 List<Integer> list = clmMap.get( clm ); 340 if( list == null ) { return -1; } 341 342 for( int i=0; i<list.size(); i++ ) { 343 int intKey = list.get( i ); 344 if( isMark[intKey] != MARK_NULL ) { 345 if( isMark[intKey] == MARK_TRUE ) { return intKey; } 346 else { continue; } 347 } 348 349 final String onMark ; 350 if( markCmlNo[intKey] < 0 ) { onMark = markKey[intKey] ; } 351 else { onMark = table.getValue( row,markCmlNo[intKey] ); } 352 353 // 3.5.4.0 (2003/11/25) 追加 354 if( onMark == null || onMark.length() == 0 ) { continue; } 355 356 final String markList ; 357 if( markListNo[intKey] < 0 ) { markList = markLists[intKey] ; } 358 else { markList = table.getValue( row,markListNo[intKey] ); } 359 360 // 3.5.4.0 (2003/11/25) 修正 361 if( markList == null || markList.length() == 0 ) { continue; } 362 363 if( markList.indexOf( onMark ) >= 0 ) { return intKey; } 364 } 365 return -1; 366 } 367 368 /** 369 * マーカーされたカラム番号の配列を返します。 370 * 371 * これは特殊処理で、Edit機能で、カラム列をキャッシュしているときに、 372 * JSPのソース等の変更時に、変更が反映されない対応を行う場合、 373 * 通常の ViewFormのサブクラスから、Edit専用の ViewForm_HTMLSeqClmTable で 374 * 制御する場合、ViewMarkerのEditMarkerでは、通常非表示(検索の場合)ですが 375 * Editのポップアップ画面に、表示されてしまうのを避けるため、noDisplay に 376 * 強制的にするカラム番号が必要です。 377 * あくまで、暫定処置です。Edit機能を改修するときに、この機能は削除します。 378 * 379 * ※ この処理は、EditMarkerでのみ有効にします。 380 * 381 * @og.rev 5.8.6.0(2015/04/03) 6.0.3.0の移植 382 * 383 * @return マーカーされたカラム番号の配列 384 */ 385 public int[] getColumnNos() { 386 int[] rtn = new int[clmMap.size()]; 387 int i=0; 388 for( final Integer obj : clmMap.keySet() ) { 389 rtn[i++] = obj.intValue(); 390 } 391 392 return rtn; 393 } 394}