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