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,Formatter> formMap = new HashMap<Integer,Formatter>(); 048 private DBTableModel table = null; 049 private int[] markCmlNo = null; 050 private int[] isMark = null; 051 private static final int MARK_NULL = -1; // マーカー未設定 052 private static final int MARK_TRUE = 1; // マーカー作成 053 private static final int MARK_FALSE = 0; // マーカー作成せず 054 // 3.5.2.0 (2003/10/20) 055 private String[] markKey = null; 056 private String[] markLists = null; 057 private String[] instrVals = null; // 3.8.8.1 (2007/01/06) 058 private int[] markListNo = null; 059 private boolean[] useFmtDeco = null; // 5.6.3.0 (2013/04/01) [$XXXX],[#XXXX]機能を有効にするかどうか(true:有効) 060 061 private Map<Integer,List<Integer>> clmMap = new HashMap<Integer,List<Integer>>(); // 4.0.0 (2005/08/31) 062 063 /** 064 * 内容をクリア(初期化)します。 065 * 066 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 067 * @og.rev 3.5.2.0 (2003/10/20) markLists,markListNo,markKey属性を追加 068 * @og.rev 3.5.6.1 (2004/06/25) formMap属性を追加 069 * @og.rev 3.8.8.1 (2007/01/06) instrVals属性を追加 070 * @og.rev 5.6.3.0 (2013/04/01) useFmtDeco属性を追加 071 * 072 */ 073 public void clear() { 074 markData = null; // 4.0.0 (2005/08/31) 075 formMap = new HashMap<Integer,Formatter>(); 076 table = null; 077 isMark = null; 078 markKey = null; 079 markLists = null; 080 instrVals = null; // 3.8.8.1 (2007/01/06) 081 markListNo = null; 082 clmMap = new HashMap<Integer,List<Integer>>(); // 4.0.0 (2005/08/31) 083 useFmtDeco = null; // 5.6.3.0 (2013/04/01) [$XXXX],[#XXXX]機能を有効にするかどうか(true:有効) 084 } 085 086 /** 087 * カラムに対するマーカーアトリビュートをセットします。 088 * 089 * @og.rev 3.1.0.0 (2003/03/20) Hashtable を使用している箇所で、非同期でも構わない箇所を、HashMap に置換え。 090 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 091 * 092 * @param attri アトリビュート 093 */ 094 public void addAttribute( final Attributes attri ) { 095 if( markData == null ) { markData = new ArrayList<Attributes>(); } 096 markData.add( attri ); 097 } 098 099 /** 100 * 内部に DBTableModel をセットします。 101 * 102 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 103 * @og.rev 3.5.2.0 (2003/10/20) markLists,markListNo,markKey属性を追加 104 * @og.rev 3.5.6.1 (2004/06/25) DBTableModel の再設定に対応。 105 * @og.rev 3.8.8.1 (2007/01/06) instrVals属性を追加 106 * @og.rev 5.6.3.0 (2013/04/01) useFmtDeco属性を追加 107 * 108 * @param tbl DBTableModelオブジェクト 109 */ 110 public void setDBTableModel( final DBTableModel tbl ) { 111 table = tbl; 112 int count = markData.size(); // 4.0.0 (2005/08/31) 113 114 isMark = new int[ count ]; 115 markKey = new String[ count ]; 116 markCmlNo = new int[ count ]; 117 markLists = new String[ count ]; 118 instrVals = new String[ count ]; 119 markListNo = new int[ count ]; 120 useFmtDeco = new boolean[ count ]; // 5.6.3.0 (2013/04/01) [$XXXX],[#XXXX]機能を有効にするかどうか(true:有効) 121 122 Arrays.fill( isMark,MARK_FALSE ); // マーカーの表示可否 123 Arrays.fill( markCmlNo,-1 ); // マーカーの可否を判断するカラム番号 124 Arrays.fill( useFmtDeco,false ); // [$XXXX],[#XXXX]機能を無効にする。(互換性のため) 125 126 for( int intKey=0; intKey<count; intKey++ ) { 127 Attributes attri = markData.get( intKey ); 128 129 String column = attri.get( "column" ); 130 int clm = table.getColumnNo( column ); 131 List<Integer> list = clmMap.get( clm ); 132 if( list == null ) { list = new ArrayList<Integer>(); } 133 list.add( intKey ); 134 clmMap.put( clm,list ); 135 136 String body = attri.get( "body" ); 137 Formatter formatter = new Formatter( table ); 138 formatter.setFormat( body ); 139 formMap.put( intKey, formatter ); 140 141 makeOnMarkFormat( intKey,attri ); 142 143 useFmtDeco[intKey] = "true".equalsIgnoreCase( attri.get( "useFormatDeco" ) ); // 5.6.3.0 (2013/04/01) 144 } 145 } 146 147 /** 148 * 指定の行列に対するマーカー文字列を返します。 149 * この値は,すでにマーカー文字列処理されている為, RendererValue で 150 * 変換する必要はありません。 151 * 引数の value はそのカラムの値として利用されます。この値は、修飾済みの 152 * 値を与えることが可能です。 153 * 154 * @og.rev 3.5.6.1 (2004/06/25) formMap属性を使用します。 155 * @og.rev 3.8.8.1 (2007/01/06) instrVals属性を追加 156 * @og.rev 5.3.9.0 (2011/09/01) カラム名の先頭に'$'を付加した場合に、URLEncodeされた値を返すように対応 157 * @og.rev 5.6.3.0 (2013/04/01) useFmtDeco属性を追加([$XXXX],[#XXXX]機能を有効にするかどうか) 158 * 159 * @param row 指定の行 160 * @param clm 指定の列 161 * @param value カラムの値 162 * 163 * @return row行,colum列 のマーカー文字列 164 */ 165 public String getMarkerString( final int row,final int clm,final String value ) { 166 int intKey = isOnMark(row,clm) ; 167 if( intKey < 0 ) { return value; } 168 169 Formatter formatter = formMap.get( intKey ); 170 int[] clmNo = formatter.getClmNos(); 171 String[] format = formatter.getFormat(); 172 173 char[] types = formatter.getType(); 174 175 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_LARGE ); 176 int j=0; 177 String val ; 178 for( ; j<clmNo.length; j++ ) { 179 if( clm == clmNo[j] ) { 180 val = value; 181 } 182 else { 183 val = formatter.getValue(row,clmNo[j]); 184 } 185 186 // 5.6.3.0 (2013/04/01) useFmtDeco属性を追加(trueの場合は、[$XXXX],[#XXXX]機能を有効にする) 187 if( useFmtDeco[intKey] ) { 188 DBColumn dbClm = table.getDBColumn( clmNo[j] ); 189 if( types[j] == '$' ) { 190 val = dbClm.getRendererValue( row,val ); 191 } 192 else if( types[j] == '#' ) { 193 val = dbClm.getLabel(); 194 } 195 } 196 // false が以前と同じ処理(互換処理)ただし、view などのフォーマット処理とは異なる。 197 else { 198 // 5.3.9.0 (2011/09/01) カラム名の先頭に'$'を付加した場合URLEncodeされた値を返すように対応 199 if( types[j] == '$' ) { 200 val = StringUtil.urlEncode( val ); 201 } 202 } 203 204 buf.append( format[j] ); 205 buf.append( val ); 206 } 207 if( j < format.length ) { buf.append( format[j] ); } 208 String rtn = StringUtil.replace( buf.toString(),"{I}",String.valueOf( row ) ); 209 210 // 3.8.8.1 (2007/01/06) instrVals属性を追加 211 if( instrVals[intKey] != null ) { 212 String[] vals = StringUtil.csv2Array( instrVals[intKey],' ' ); 213 for( int i=0; i<vals.length; i++ ) { 214 String css = "<span class=\"instr" + i + "\">" + vals[i] + "</span>"; 215 rtn = StringUtil.replace( rtn,vals[i],css ); 216 } 217 } 218 return rtn ; 219 } 220 221 /** 222 * マーカーを作成する/作成しないの指定カラム番号を求めます。 223 * また、int[列番号] isMark を初期化します。 224 * 225 * @og.rev 3.5.2.0 (2003/10/20) markLists,markListNo,markKey属性を追加 226 * @og.rev 3.8.8.1 (2007/01/06) instrVals属性を追加 227 * 228 * @param intKey カラムキーの番号 229 * @param attri アトリビュート 230 */ 231 private void makeOnMarkFormat( final int intKey,final Attributes attri ) { 232 String onMark = attri.get( "onMark" ); 233 String markList = attri.get( "markList" ); 234 instrVals[intKey] = attri.get( "instrVals" ); // 3.8.8.1 (2007/01/06) 235 236 // 3.5.6.0 (2004/06/18) nullポインタの参照外しバグの対応 237 // このロジックで値が設定済みであれば、以下の処理は不要である。 238 isMark[intKey] = MARK_NULL; 239 if( onMark == null || onMark.length() == 0 || 240 markList == null || markList.length() == 0 ) { 241 isMark[intKey] = MARK_FALSE; 242 return ; // 3.5.6.0 (2004/06/18) 243 } 244 else if( onMark.charAt( 0 ) != '[' && markList.charAt( 0 ) != '[' ) { 245 isMark[intKey] = ( markList.indexOf( onMark ) >= 0 ) ? MARK_TRUE : MARK_FALSE; 246 return ; // 3.5.6.0 (2004/06/18) 247 } 248 249 if( onMark.charAt( 0 ) == '[' ) { 250 markCmlNo[intKey] = table.getColumnNo( onMark.substring( 1,onMark.length()-1 )); 251 } 252 else { 253 markCmlNo[intKey] = -1; 254 markKey[intKey] = onMark ; 255 } 256 257 if( markList.charAt( 0 ) == '[' ) { 258 markListNo[intKey] = table.getColumnNo( markList.substring( 1,markList.length()-1 )); 259 } 260 else { 261 markListNo[intKey] = -1; 262 markLists[intKey] = markList; 263 } 264 } 265 266 /** 267 * マーカーを作成するかどうかを判断します。 268 * int[列番号] isMark には、 未設定 FALSE TRUE の状態を持っており、 269 * 列でマーカーを作成する状態が固定の場合(例えば,onMark属性がデフォルト "true" の場合) 270 * カラムに関係なく、同じ値を返すときに、使用します。 271 * 272 * @og.rev 3.5.2.0 (2003/10/20) markLists,markListNo,markKey属性を追加 273 * @og.rev 3.5.4.0 (2003/11/25) onMark ,markList が null(またはゼロストリング)の場合は、false とする。 274 * @og.rev 4.0.0.0 (2005/08/31) 同一カラムの複数登録を許可します。 275 * 276 * @param row 列番号 277 * @param clm カラムキーの名称 278 * 279 * @return 処理するリスト番号、-1 の場合は、該当なし 280 */ 281 private int isOnMark( final int row,final int clm ) { 282 List<Integer> list = clmMap.get( clm ); 283 if( list == null ) { return -1; } 284 285 for( int i=0; i<list.size(); i++ ) { 286 int intKey = list.get( i ); 287 if( isMark[intKey] != MARK_NULL ) { 288 if( isMark[intKey] == MARK_TRUE ) { return intKey; } 289 else { continue; } 290 } 291 292 final String onMark ; 293 if( markCmlNo[intKey] < 0 ) { onMark = markKey[intKey] ; } 294 else { onMark = table.getValue( row,markCmlNo[intKey] ); } 295 296 // 3.5.4.0 (2003/11/25) 追加 297 if( onMark == null || onMark.length() == 0 ) { continue; } 298 299 final String markList ; 300 if( markListNo[intKey] < 0 ) { markList = markLists[intKey] ; } 301 else { markList = table.getValue( row,markListNo[intKey] ); } 302 303 // 3.5.4.0 (2003/11/25) 修正 304 if( markList == null || markList.length() == 0 ) { continue; } 305 306 if( markList.indexOf( onMark ) >= 0 ) { return intKey; } 307 } 308 return -1; 309 } 310}