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.hayabusa.html;
017    
018    import org.opengion.hayabusa.common.HybsSystem;
019    import org.opengion.hayabusa.db.DBTableModel;
020    import org.opengion.hayabusa.db.DBColumn;
021    import org.opengion.fukurou.util.StringUtil;
022    import org.opengion.fukurou.util.Attributes;
023    import org.opengion.fukurou.model.Formatter;
024    
025    import java.util.Map;
026    import java.util.HashMap;
027    import java.util.List;
028    import java.util.ArrayList;
029    import 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     */
044    public 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) カラãƒ?��の先é?に'$'を付加した場å�?RLEncodeされたå?を返すように対å¿?
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    }