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 */
016 package org.opengion.fukurou.model;
017
018 import java.util.ArrayList;
019 import java.util.List;
020
021
022 /**
023 * [PN],[OYA] などの [] でæŒ?®šされたカラãƒ?�§表されたフォーマットデータに対してã€?
024 * DataModel オブジェクトを適用して å�?‚«ラãƒ?�«実データを割り当てるオブジェクトですã?
025 *
026 * カラãƒ?��には、特殊カラãƒ?��が使用できますã?これは、DataModel に存在しなã�?‚«ラãƒ?��
027 * ですが、å?を返すことがå?来ますã?
028 * <pre>
029 * [KEY.カラãƒ?��] : 行番号付きカラãƒ?��
030 * [I] : 行番号
031 * [ROW.ID] : 行毎ã?チェãƒ?‚¯ボックスのID
032 * [ROW.JSON] : 行毎ã?全ãƒ??タのJavaScriptオブジェクト形å¼?{ key:val,key:val,... }
033 * カラãƒ??前に修飾記号(#,$,!)を付けるとフォーマットを変更できますã?
034 * ただしã?FormatTextField 系 と FormatTable 系で、å?力される形式が異なりますã?
035 * FormatTextField 系 FormatTable 系
036 * [#カラãƒ?��] : TDなしã?ラベルと入力フィールãƒ? ラベルをå?åŠ?
037 * [$カラãƒ?��] : TDなしã?入力フィールドã?み レンãƒ?ƒ©ーをå?åŠ?
038 * [!カラãƒ?��] : TDなしã?値のみ 値をå?åŠ?
039 *
040 * </pre>
041 * @og.group 画面表示
042 *
043 * @version 4.0
044 * @author Kazuhiko Hasegawa
045 * @since JDK5.0,
046 */
047 public class Formatter {
048 /** カラãƒ?D(連結文字å?)行番号の連結文字å?を定義 {@value} */
049 public static final String JOINT_STRING = "__" ;
050
051 /** ãƒ??ブル表示のチェãƒ?‚¯ボックスを特定すã‚?id の 名称( id は、この名称?‹行番号) {@value} */
052 public static final String ROW_ID_KEY = "cb"; // 3.6.0.0 (2004/09/17)
053
054 /** 特殊カラãƒ?��の定義: 行番号 [I] */
055 public static final int SYS_ROWNUM = -1; // [KEY.カラãƒ?��],[I],[ROW.ID]
056 /** 特殊カラãƒ?��の定義: [ROW.JSON] */
057 public static final int SYS_JSON = -2; // [ROW.JSON]
058
059 private final DataModel<?> model ; // 4.3.3.6 (2008/11/15) Generics警告対å¿?
060 private int[] clmNos = null; // フォーマットã?カラãƒ?•ª号配å?
061 private String[] format = null;
062 private String[] clmKeys = null; // フォーマットã?カラãƒ?��配å?
063 private char[] type = null; // '#':ラベルのみ '$':レンãƒ?ƒ©ー '!':値のみ そã?ä»?通常
064
065 /**
066 * ãƒ??タモãƒ?ƒ«を指定してフォーマッターを構築しますã?
067 *
068 * @param model ãƒ??タモãƒ?ƒ«
069 */
070 public Formatter( final DataModel<?> model ) { // 4.3.3.6 (2008/11/15) Generics警告対å¿?
071 this.model = model;
072 }
073
074 /**
075 * フォーマットをセãƒ?ƒˆしますã?
076 *
077 * @param fmt [カラãƒ?��] 形式ã?フォーマットデータ
078 */
079 public void setFormat( final String fmt ) {
080 makeFormatList( fmt );
081 advanceFormat();
082 }
083
084 /**
085 * フォーマットをセãƒ?ƒˆしますã?
086 *
087 * @param fmt [カラãƒ?��] 形式ã?フォーマットデータ
088 */
089 private void makeFormatList( final String fmt ) {
090 int start = 0;
091 int index = fmt.indexOf( '[' );
092 List<String> clmKeyList = new ArrayList<String>();
093 List<String> formatList = new ArrayList<String>();
094 while( index >= 0 ) {
095 int end = fmt.indexOf( ']',index );
096 if( end < 0 ) {
097 String errMsg = "[ と ] との対応関係がずれてã�?�¾すã?"
098 + "format=[" + fmt + "] : index=" + index ;
099 throw new RuntimeException( errMsg );
100 }
101
102 // [ より前方のæ–?—å?は、formatList へ
103 if( index > 0 ) { formatList.add( fmt.substring( start,index ) ); }
104 else { formatList.add( "" ); } // ][ と連続してã�?‚‹ケース
105
106 // [XXXX] の XXXX部åˆ?‚’処ç�?
107 clmKeyList.add( fmt.substring( index+1,end ) );
108
109 start = end+1 ;
110 index = fmt.indexOf( '[',start );
111 }
112 // ] の後方部åˆ??、formatList へ
113 formatList.add( fmt.substring( start ) );
114
115 format = formatList.toArray( new String[formatList.size()] );
116 clmKeys = clmKeyList.toArray( new String[clmKeyList.size()] );
117 }
118
119 /**
120 * 追åŠ?©Ÿè?フォーマットを作æ?しますã?
121 *
122 */
123 private void advanceFormat() {
124
125 int size = clmKeys.length ;
126 clmNos = new int[size];
127 type = new char[size];
128
129 // カラãƒ?•ª号の設定と、特殊カラãƒ?��処ç�?
130 String clm ;
131 for( int i=0; i<size; i++ ) {
132 clm = clmKeys[i];
133 char ch = clm.charAt(0);
134 if( ch == '#' || ch == '$' || ch == '!' ) {
135 type[i] = ch;
136 clm = clm.substring(1);
137 clmKeys[i] = clm;
138 clmNos[i] = model.getColumnNo( clm );
139 }
140 // [KEY.カラãƒ?��] 機è?追åŠ?
141 else if( clm.startsWith( "KEY." ) ) {
142 clmNos[i] = SYS_ROWNUM;
143 format[i] = format[i] + clm.substring(4) + JOINT_STRING ;
144 }
145 // [I] 機è?追åŠ?
146 else if( "I".equals( clm ) ) {
147 clmNos[i] = SYS_ROWNUM;
148 }
149 // [ROW.ID] 機è?追åŠ?
150 else if( "ROW.ID".equals( clm ) ) {
151 clmNos[i] = SYS_ROWNUM;
152 format[i] = format[i] + ROW_ID_KEY ;
153 }
154 // [ROW.JSON] 機è?追åŠ?
155 else if( "ROW.JSON".equals( clm ) ) {
156 clmNos[i] = SYS_JSON;
157 }
158 else {
159 clmNos[i] = model.getColumnNo( clm );
160 }
161 }
162 }
163
164 /**
165 * column にあるセルの属æ?値をStringに変換して返しますã?
166 *
167 * @param row 処ç�?¸の行番号
168 * @param clm 値が参照されるカラãƒ?•ª号
169 *
170 * @return æŒ?®šされたセルの値
171 *
172 */
173 public String getValue( final int row,final int clm ) {
174 final String rtn ;
175 if( clm >= 0 ) {
176 rtn = String.valueOf( model.getValue( row,clm ) );
177 }
178 else if( clm == SYS_ROWNUM ) {
179 rtn = String.valueOf( row );
180 }
181 else if( clm == SYS_JSON ) {
182 rtn = getJson( row );
183 }
184 else {
185 String errMsg = "æŒ?®šã?カラãƒ?•ª号に該当するå?ç�?�Œ見つかりませんã€?
186 + "clm=[" + clm + "]" ;
187 throw new RuntimeException( errMsg );
188 }
189
190 return rtn ;
191 }
192
193 /**
194 * æŒ?®šã? 行番号に対する、DataModel をå?に作æ?したフォーマット文字å?を返しますã?
195 *
196 * @param row 行番号( [I]フォーマットå?ç�?”¨ )
197 *
198 * @return æŒ?®šã?Object配å?をå?に作æ?したフォーマット文字å?
199 */
200 public String getFormatString( final int row ) {
201 // StringBuilder rtnStr = new StringBuilder( 200 );
202 //
203 // int count = clmNos.length;
204 // for( int i=0; i<count; i++ ) {
205 // rtnStr.append( format[i] );
206 // if( clmNos[i] == SYS_ROWNUM ) {
207 // rtnStr.append( row );
208 // }
209 // else if( clmNos[i] == SYS_JSON ) {
210 // rtnStr.append( getJson( row ) );
211 // }
212 // else {
213 // rtnStr.append( model.getValue( row,clmNos[i] ) );
214 // }
215 // }
216 // rtnStr.append( format[count] );
217 //
218 // return rtnStr.toString();
219 return getFormatString( row, null );
220 }
221
222 /**
223 * æŒ?®šã? 行番号に対する、DataModel をå?に作æ?したフォーマット文字å?を返しますã?
224 * ãƒ??タはseparatorでæŒ?®šされた区åˆ?‚Šæ–?—で囲まれて返されますã?
225 *
226 * @og.rev 4.3.1.1 (2008/08/23) switch に、default label が存在しなã�?�Ÿめã?追åŠ?
227 *
228 * @param row 行番号( [I]フォーマットå?ç�?”¨ )
229 * @param separator セパレーター
230 *
231 * @return æŒ?®šã?Object配å?をå?に作æ?したフォーマット文字å?
232 */
233 public String getFormatString( final int row, final String separator ) {
234 StringBuilder rtnStr = new StringBuilder( 200 );
235
236 int count = clmNos.length;
237 for( int i=0; i<count; i++ ) {
238 rtnStr.append( format[i] );
239 if( clmNos[i] == SYS_ROWNUM ) {
240 rtnStr.append( row );
241 }
242 else if( clmNos[i] == SYS_JSON ) {
243 rtnStr.append( getJson( row ) );
244 }
245 else {
246 if( separator == null || separator.length() == 0 ) {
247 rtnStr.append( model.getValue( row,clmNos[i] ) );
248 }
249 else {
250 // 4.3.1.1 (2008/08/23) default label が存在しなã�?�Ÿめã?追åŠ?
251 switch( model.getNativeType( clmNos[i] ) ) {
252 case INT:
253 case LONG:
254 case DOUBLE:
255 rtnStr.append( model.getValue( row,clmNos[i] ) );
256 break;
257 case STRING:
258 case CALENDAR:
259 rtnStr.append( separator ).append( model.getValue( row,clmNos[i] ) ).append( separator );
260 break;
261 default:
262 throw new AssertionError( "Unexpected enumrated value! " + model.getNativeType( clmNos[i] ) );
263 }
264 }
265 }
266 }
267 rtnStr.append( format[count] );
268
269 return rtnStr.toString();
270 }
271
272 /**
273 * 先ã?フォーマット情報の[カラãƒ?��]をã?? に置き換えたフォーマットを返しますã?
274 * これは、java.sql.PreparedStatement 形式ã?Queryæ–?—å?を合成するå?合に使用しますã?
275 *
276 * @return PreparedStatement形式ã?Queryæ–?—å?
277 */
278 public String getQueryFormatString() {
279 StringBuilder rtnStr = new StringBuilder( 200 );
280
281 int count = clmKeys.length;
282 for( int i=0; i<count; i++ ) {
283 rtnStr.append( format[i] ).append( '?' );
284 }
285 rtnStr.append( format[count] );
286
287 return rtnStr.toString();
288 }
289
290 /**
291 * フォーマットã?カラãƒ?��配å?を返しますã?
292 *
293 * @return フォーマットã?カラãƒ?��配å?
294 */
295 public String[] getClmKeys() {
296 return clmKeys.clone();
297 }
298
299 /**
300 * フォーマットã?カラãƒ?•ª号配å?を返しますã?
301 *
302 * @return フォーマットã?カラãƒ?•ª号配å?
303 */
304 public int[] getClmNos() {
305 return clmNos.clone();
306 }
307
308 /**
309 * フォーマットé?列を返しますã?
310 *
311 * @return フォーマットé?åˆ?
312 */
313 public String[] getFormat() {
314 return format.clone();
315 }
316
317 /**
318 * タイプ文字å?配å?を返しますã?
319 * タイプとは、[XXX] の記述で、[#XXX] は、XXXカラãƒ??ラベルをã?[$XXX]は、XXXカラãƒ??
320 * レンãƒ?ƒ©ーをã?[!XXX} は、å?のみ取り出す指定を行いますã?
321 * 主に、TextField系のフォーマットとTable系では、意味合いが異なりますã?でã€?
322 * ご注意くã�?�•ã�??
323 *
324 * @return タイプ文字å?配å? '#':ラベルのみ '$':レンãƒ?ƒ©ー '!':値のみ そã?ä»?通常
325 */
326 public char[] getType() {
327 return type.clone();
328 }
329
330 /**
331 * 行毎ã?全ãƒ??タのJavaScriptオブジェクト形å¼?を返しますã?
332 *
333 * JavaScriptオブジェクト形式とは、{ key:val,key:val,... }の形式でã€?
334 * ここでは、å?部設定された DataModel のすべてのカラãƒ?��をキーにã€?
335 * 引数で渡されã�?配å?ã‚?値として使用しますã?
336 *
337 * @param row (DataModelの)行番号
338 *
339 * @return æŒ?®šã?行番号に対応するå?ãƒ??タのJSON形式データ
340 */
341 public String getJson( final int row ) {
342 String[] names = model.getNames();
343 Object[] vals = model.getValues( row );
344
345 StringBuilder rtnStr = new StringBuilder( 200 );
346
347 rtnStr.append( "{'I':'" ).append( row ).append( "'" ); // 行番号
348
349 for( int i=0; i<names.length; i++ ) {
350 rtnStr.append( ",'" ).append( names[i] ).append( "':'" );
351 rtnStr.append( vals[i] ).append( "'" );
352 }
353 rtnStr.append( "}" );
354
355 return rtnStr.toString();
356 }
357 }