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    }