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.plugin.view;
017
018import java.util.List;
019
020import org.opengion.fukurou.util.StringUtil;
021import org.opengion.fukurou.util.TagBuffer;
022import org.opengion.fukurou.util.XHTMLTag;
023import org.opengion.hayabusa.common.HybsSystem;
024import org.opengion.hayabusa.common.HybsSystemException;
025import org.opengion.hayabusa.html.FormatterType;
026import org.opengion.hayabusa.html.TableFormatter;
027import org.opengion.hayabusa.html.ViewAjaxTreeTableParam;
028
029/**
030 * JavaScript のツリー階層を持ったテーブル表示を行う、ツリーテーブル表示クラスです。
031 *
032 * AbstractViewForm により、setter/getterメソッドのデフォルト実装を提供しています。
033 * 各HTMLのタグに必要な setter/getterメソッドのみ,追加定義しています。
034 *
035 * AbstractViewForm を継承している為,ロケールに応じたラベルを出力させる事が出来ます。
036 *
037 * @og.group 画面表示
038 *
039 * @version  4.0
040 * @author   Hiroki Nakamura
041 * @since    JDK5.0,
042 */
043public class ViewForm_HTMLAjaxTreeTable extends ViewForm_HTMLCustomTable  {
044        //* このプログラムのVERSION文字列を設定します。   {@value} */
045        private static final String VERSION = "4.3.7.4 (2009/07/01)" ;
046
047        private static final String JSP = HybsSystem.sys( "JSP" );
048
049        private int[]                   childSearchKeys = null;
050        private String                  childSearchJsp  = null;
051        private String                  levelClm                = null;
052        private int                             levelClmPos             = -1;
053        private String                  imgCollapsed    = null;
054        private String                  imgExpanded     = null;
055        private String                  imgNoSub        = null;
056        private boolean                 expandAll               = false; // 4.3.3.0 (2008/10/01)
057        private int                             childViewStartNo= -1; // 4.3.3.0 (2008/10/01)
058//      private String                  expCtrlClm              = null; // 4.3.5.0 (2008/02/01)
059        private int                             expCtrlClmPos   = -1; // 4.3.5.0 (2008/02/01)
060
061        // 4.3.4.4 (2009/01/01)
062//      /**
063//       * デフォルトコンストラクター
064//       *
065//       */
066//      public ViewForm_HTMLAjaxTreeTable() {
067//              super();
068//      }
069
070        /**
071         * DBTableModel から HTML文字列を作成して返します。
072         * startNo(表示開始位置)から、pageSize(表示件数)までのView文字列を作成します。
073         * 表示残りデータが pageSize 以下の場合は,残りのデータをすべて出力します。
074         *
075         * @og.rev 4.3.3.0 (2008/10/01) noTransition属性,childViewStartNo属性対応
076         * @og.rev 4.3.7.4 (2009/07/01) tbodyタグの入れ子を解消(FireFox対応)
077         *
078         * @param  strNo     表示開始位置
079         * @param  pageSize  表示件数
080         *
081         * @return  DBTableModelから作成された HTML文字列
082         */
083        @Override
084        public String create( final int strNo, final int pageSize )  {
085                if( getRowCount() == 0 ) { return ""; } // 暫定処置
086
087                initParam();
088
089                // 4.3.3.0 (2008/10/01) 子データ差分取得用
090                int startNo = 0;
091                if( childViewStartNo >= 0 )  { startNo = childViewStartNo; }
092                else                                            { startNo = strNo; }
093
094                int lastNo = getLastNo( startNo, pageSize );
095
096                StringBuilder out = new StringBuilder( HybsSystem.BUFFER_LARGE );
097
098                if( headerFormat == null ) {
099                        makeDefaultFormat();
100                }
101
102                headerFormat.makeFormat( getDBTableModel() );
103
104                out.append( getCountForm( startNo,pageSize ) );
105                out.append( getHeader() );
106
107                if( bodyFormatsCount == 0 ) {
108                        bodyFormats = new TableFormatter[BODYFORMAT_MAX_COUNT];
109                        bodyFormats[0] = headerFormat ;
110                        bodyFormatsCount ++ ;
111                }
112                else {
113                        for( int i=0; i<bodyFormatsCount; i++ ) {
114                                bodyFormats[i].makeFormat( getDBTableModel() );
115                        }
116                }
117
118//              out.append("<tbody>").append( HybsSystem.CR ); // 4.3.7.4 (2009/07/01)
119                int bgClrCnt = 0;
120                for( int row=startNo; row<lastNo; row++ ) {
121//                      if( isSkip( row ) ) { continue; }               // 3.5.3.1 (2003/10/31)
122                        if( isSkip( row ) || isSkipNoEdit( row ) ) { continue; } // 4.3.1.0 (2008/09/08)
123                        for( int i=0; i<bodyFormatsCount; i++ ) {
124                                TableFormatter bodyFormat = bodyFormats[i];
125                                if( ! bodyFormat.isUse( row,getDBTableModel() ) ) { continue; }         // 3.5.4.0 (2003/11/25)
126                                out.append("<tbody").append( getBgColorCycleClass( bgClrCnt++,row ) );
127                                if( isNoTransition() ) { // 4.3.3.0 (2008/10/01)
128                                        out.append( getHiddenRowValue( row ) );
129                                }
130                                out.append(">");     // 3.7.0.3 (2005/03/01)
131                                out.append( bodyFormat.getTrTag() );
132
133                                if( isNumberDisplay() ) {
134                                        String ckboxTD = "<td" + bodyFormat.getRowspan() + ">";
135                                        out.append( makeCheckbox( ckboxTD,row,0 ) );
136                                }
137
138                                int cl = 0;
139                                for( ; cl < bodyFormat.getLocationSize(); cl++ ) {
140                                        String fmt = bodyFormat.getFormat(cl);
141                                        int loc = bodyFormat.getLocation(cl);
142                                        if( ! bodyFormat.isNoClass() && loc >= 0 ) {
143                                                StringBuilder newtg = new StringBuilder( HybsSystem.BUFFER_LARGE );
144                                                newtg.append("<td class=\"");
145                                                newtg.append( getColumnDbType(loc) );
146                                                newtg.append("\" ");
147                                                String tdclass = newtg.toString();
148                                                fmt = StringUtil.replace( bodyFormat.getFormat(cl) ,"<td", tdclass );
149                                        }
150                                        out.append( fmt );
151                                        if( loc >= 0 ) {
152                                                if( levelClm != null && levelClm.equals( getDBColumn( loc ).getName() ) ) {
153                                                        out.append( getLvlClmTag( row ) );
154                                                }
155                                                else {
156                                                        switch( bodyFormat.getType(cl) ) {
157                                                                case '#' : out.append( getColumnLabel(loc) );           break;
158                                                                case '$' : out.append( getRendererValue(row,loc) );     break;
159                                                                case '!' : out.append( getValue(row,loc) );                     break;
160                                                                default  : out.append( getValueLabel(row,loc) );        break;
161                                                        }
162                                                }
163                                        }
164                                        else {
165                                                out.append( bodyFormat.getSystemFormat(row,loc) );
166                                        }
167                                }
168                                out.append( bodyFormat.getFormat(cl) );
169                                out.append("</tbody>").append( HybsSystem.CR );
170                        }
171
172//                      if( hsc > 0 && hscCnt % hsc == 0 ) {
173//                              out.append("<tbody class=\"row_h\"").append(" >");
174//                              out.append( getHeadLine() );
175//                              out.append("</tbody>");
176//                              hscCnt = 1;
177//                      }
178//                      else {
179//                              hscCnt ++ ;
180//                      }
181                }
182
183                if( footerFormat != null ) {
184                        out.append( getTableFoot() );
185                }
186
187//              out.append("</tbody>").append( HybsSystem.CR ); // 4.3.7.4 (2009/07/01)
188                out.append("</table>").append( HybsSystem.CR );
189
190                out.append( getScrollBarEndDiv() );
191
192                out.append( getParameterTag() );
193
194                return out.toString();
195        }
196
197        /**
198         * フォーマットを設定します。
199         *
200         * @param       list    TableFormatterのリスト
201         */
202        @Override
203        public void setFormatterList( final List<TableFormatter> list ) {         // 4.3.3.6 (2008/11/15) Generics警告対応
204                bodyFormats = new TableFormatter[BODYFORMAT_MAX_COUNT];
205
206                bodyFormatsCount = 0;
207                for( int i=0; i<list.size(); i++ ) {
208                        TableFormatter format = list.get( i );          // 4.3.3.6 (2008/11/15) Generics警告対応
209                        switch( format.getFormatType() ) {
210                                case TYPE_HEAD : headerFormat = format; break;
211                                case TYPE_BODY : bodyFormats[bodyFormatsCount++] = format; break;
212                                case TYPE_FOOT : footerFormat = format; break;
213                                default : String errMsg = "FormatterType の定義外の値が指定されました。";
214                                // 4.3.4.4 (2009/01/01)
215                                  throw new HybsSystemException( errMsg );
216                        }
217                }
218
219//              if( headerFormat == null ) {
220//                      String errMsg = "og:thead タグの、フォーマットの指定は必須です。";
221//                      throw new HybsSystemException( errMsg );
222//              }
223        }
224
225        /**
226         * フォーマッターが設定されていない場合は、DBTableModelの情報からデフォルトの
227         * フォーマッターを作成します。
228         *
229         * @og.rev 4.3.3.6 (2008/11/15) columnDisplay,noDisplay対応
230         * @og.rev 4.3.5.0 (2008/02/01) 全展開コントロール用カラムへの対応
231         */
232        private void makeDefaultFormat() {
233                StringBuilder buf = new StringBuilder();
234                String[] clms = getDBTableModel().getNames();
235                buf.append( "<tr>" );
236                for ( int i = 0; i < clms.length; i++ ) {
237                        if( isColumnDisplay( i ) && i != expCtrlClmPos ) { // 4.3.3.6 (2008/11/15) // 4.3.5.0 (2008/02/01)
238                                buf.append( "<td>[" + clms[i] + "]</td>" );
239                        }
240                }
241                buf.append( "</tr>" );
242
243                TableFormatter formatter = new TableFormatter();
244                formatter.setFormat( buf.toString() );
245                formatter.setFormatType( FormatterType.TYPE_HEAD );
246
247                headerFormat = formatter;
248        }
249
250        /**
251         * フォーマットメソッドを使用できるかどうかを問い合わせます。
252         *
253         * @return      フォーマットメソッドを使用できるか
254         */
255        @Override
256        public boolean canUseFormat() {
257                return true;
258        }
259
260        /**
261         * 初期パラメーターを設定します。
262         *
263         * @og.rev 4.3.3.0 (2008/10/01) 初期全展開の属性追加
264         * @og.rev 4.3.5.0 (2008/02/01) 全展開時の状態をコントロールするためのフラグを追加
265         */
266        private void initParam() {
267                String[] tmp    = StringUtil.csv2Array( getParam( ViewAjaxTreeTableParam.CHILD_SEARCH_KEYS, "" ) );
268                childSearchKeys = new int[tmp.length];
269                for( int i=0; i<tmp.length; i++ ) {
270                        childSearchKeys[i] = getDBTableModel().getColumnNo( tmp[i] );
271                }
272                childSearchJsp  = getParam( ViewAjaxTreeTableParam.CHILD_SEARCH_JSP, "getChildTag.jsp" );
273                levelClm                = getParam( ViewAjaxTreeTableParam.LVL_CLM_KEY, "LVL" );
274                levelClmPos             = getDBTableModel().getColumnNo( levelClm );
275                imgCollapsed    = getParam( ViewAjaxTreeTableParam.IMG_COLLAPSED, "collapsed.gif" );
276                imgExpanded     = getParam( ViewAjaxTreeTableParam.IMG_EXPANDED, "expanded.gif" );
277                imgNoSub        = getParam( ViewAjaxTreeTableParam.IMG_NO_SUB, "nosub.gif" );
278                expandAll               = Boolean.valueOf( getParam( ViewAjaxTreeTableParam.EXPAND_ALL, "false" ) ); // 4.3.2.0 (2008/09/11)
279                childViewStartNo= Integer.valueOf( getParam( ViewAjaxTreeTableParam.CHILD_VIEW_START_NO, "-1" ) ); // 4.3.3.0 (2008/10/01)
280//              expCtrlClm              = getParam( ViewAjaxTreeTableParam.EXPAND_CONTROL_CLM_KEY, "EXPAND_CONTROL" ); // 4.3.5.0 (2008/02/01)
281                String expCtrlClm       = getParam( ViewAjaxTreeTableParam.EXPAND_CONTROL_CLM_KEY, "EXPAND_CONTROL" ); // 4.3.5.0 (2008/02/01)
282                expCtrlClmPos   = getDBTableModel().getColumnNo( expCtrlClm, false );
283        }
284
285        /**
286         * JavaScriptに渡すためのパラメータをhiddenタグで出力します。
287         *
288         * @og.rev 4.3.3.0 (2008/10/01) 初期全展開対応
289         * @og.rev 4.3.5.0 (2008/02/01) 全展開時の状態をコントロールするためのフラグを追加
290         *
291         * @param row 行番号
292         *
293         * @return HTMLタグ
294         */
295        private String getLvlClmTag( final int row ) {
296                StringBuilder keys = new StringBuilder();
297                keys.append( "command," + levelClm );
298                for( int i=0; i<childSearchKeys.length; i++ ) {
299                        keys.append( "," ).append( getColumnName( childSearchKeys[i] ) );
300                }
301
302                StringBuilder vals = new StringBuilder();
303                vals.append( "NEW," + getValue( row, levelClmPos ) );
304                for( int i=0; i<childSearchKeys.length; i++ ) {
305                        vals.append( "," ).append( getValue( row, childSearchKeys[i] ) );
306                }
307
308                String imgsrc = null;
309                StringBuilder clazz = new StringBuilder();
310                clazz.append( "lvlctl unreplaceable" );
311                if( expandAll ) { // 4.3.3.0 (2008/10/01)
312                        if( row == getRowCount() - 1
313                                        || Integer.parseInt( getValue( row, levelClmPos ) ) >= Integer.parseInt( getValue( row+1, levelClmPos ) ) ) {
314                                boolean isExp = ( expCtrlClmPos > -1 && StringUtil.nval( getValue( row, expCtrlClmPos ), false ) );
315                                if( isExp ) {
316                                        imgsrc = JSP + "/image/" + imgCollapsed;
317                                }
318                                else {
319                                        imgsrc = JSP + "/image/" + imgNoSub;
320                                        clazz.append( " fetched nosub" );
321                                }
322                        }
323                        else {
324                                imgsrc = JSP + "/image/" + imgExpanded;
325                                clazz.append( " fetched expanded" );
326                        }
327                }
328                else {
329                        imgsrc = JSP + "/image/" + imgCollapsed;
330                }
331
332                TagBuffer tag = new TagBuffer( "img" );
333                tag.add( "class", clazz.toString() );
334                tag.add( "src" , imgsrc );
335                tag.add( "alt" , "Level " + getValue( row, levelClmPos ) );
336                tag.add( "lvl" , getValue( row, levelClmPos ) );
337                tag.add( "keys" , keys.toString() );
338                tag.add( "vals" , vals.toString() );
339
340                return getRendererValue( row, levelClmPos ) + tag.makeTag();
341        }
342
343        /**
344         * JavaScriptに渡すためのパラメーターをhiddenタグをして出力します。
345         *
346         * @return hiddenタグ
347         */
348        private String getParameterTag() {
349                StringBuilder buf = new StringBuilder();
350                buf.append( XHTMLTag.hidden( ViewAjaxTreeTableParam.CHILD_SEARCH_JSP, childSearchJsp ) );
351                buf.append( XHTMLTag.hidden( ViewAjaxTreeTableParam.IMG_COLLAPSED, JSP + "/image/" + imgCollapsed ) );
352                buf.append( XHTMLTag.hidden( ViewAjaxTreeTableParam.IMG_EXPANDED, JSP + "/image/" + imgExpanded ) );
353                buf.append( XHTMLTag.hidden( ViewAjaxTreeTableParam.IMG_NO_SUB, JSP + "/image/" + imgNoSub ) );
354                return buf.toString();
355        }
356}