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    }