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.hayabusa.taglib;
017
018import static org.opengion.fukurou.util.StringUtil.nval;
019
020import java.util.ArrayList;
021import java.util.Collections;
022import java.util.Enumeration;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026
027import org.opengion.fukurou.util.StringUtil;
028import org.opengion.fukurou.util.TagBuffer;
029import org.opengion.hayabusa.common.HybsSystem;
030import org.opengion.hayabusa.common.HybsSystemException;
031import org.opengion.hayabusa.db.DBColumn;
032import org.opengion.hayabusa.db.DBEditConfig;
033import org.opengion.hayabusa.db.DBLastSql;
034import org.opengion.hayabusa.db.DBTableModel;
035
036/**
037 * 画面表示、集計に関する設定情報の表示、登録を行うためのタグです。
038 * (このタグは標準の設定編集画面に組み込んで使用され、各画面JSPから呼び出すことはありません)
039 *
040 * このタグは、ユーザー単位に管理されるエディット設定オブジェクトに対するI/Fの機能を
041 * 提供しています。このエディット設定オブジェクトについては、画面毎に設定を行うため、
042 * タグの呼び出しには、画面IDが必須となっています。
043 *
044 * 具体的な機能としては、3つの機能を提供します。
045 * (1)設定画面表示(command="GET")
046 *    ユーザー単位に管理されるエディット設定オブジェクトをHTMLに変換して表示
047 *    また、表示カラムの一覧(カンマ区切り)については、画面側のJavaScriptで再設定を行うため、
048 *    その値を"viewClms"という名前のhiddenタグで出力します。
049 * (2)エディット名一覧(command="LIST")
050 *    指定の画面IDに対して、設定されているエディット名の一覧をプルダウン(selectタグ)に
051 *    変換して表示します。(name="editName")
052 * (3)設定情報登録/削除(command="SET"/"DELETE")
053 *    (1)で設定された内容に対して、エディット名を指定してその内容を保存/削除します。
054 *    情報の保存は、command="GET"で表示される項目名と連動していますので、単独での使用は
055 *    できません。
056 *
057 * @og.formSample
058 * ●形式:一般ユーザーが直接組み込むことはありません。
059 * ●body:なし
060 *
061 * ●Tag定義:
062 *   <og:editConfig
063 *       command          ○【TAG】command を指定します(必須)。
064 *       gamenId          ○【TAG】画面ID を指定します(必須)。
065 *       editName           【TAG】エディット名 を指定します
066 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
067 *   />
068 *
069 * ●使用例
070 *     <og:editConfig command="{@command}" gamenId="{@gamenId}" editName="{@editName}" />
071 *
072 *     <og:editConfig
073 *         command        = command設定 (GET/LIST/SET/REMOVE)
074 *         gamenId        = "GE0000"    画面ID
075 *       [ editName ]     = "EDITNAME"  エディット名
076 *     />
077 *
078 * @og.group エディット設定
079 *
080 * @og.rev 5.3.6.0 (2011/06/01)
081 * @og.rev 5.9.18.1 (2017/03/24) T.OTA 共通の場合は編集名の頭に「*」を付与
082 *
083 * @version  5.0
084 * @author       Hiroki Nakamura
085 * @since    JDK6.0,
086 */
087public class EditConfigTag extends CommonTagSupport {
088        //* このプログラムのVERSION文字列を設定します。   {@value} */
089        private static final String VERSION = "5.7.5.2 (2014/04/11)" ;
090
091        private static final long serialVersionUID = 575220140411L ;
092
093        private static final String VIEW_PREFIX                 = "EDIT_VIEW_";
094        private static final String SUM_PREFIX                  = "EDIT_SUM_";
095        private static final String GROUP_PREFIX                = "EDIT_GROUP_";
096        private static final String SUBTOTAL_PREFIX             = "EDIT_SUBTOTAL_";
097        private static final String TOTAL_PREFIX                = "EDIT_TOTAL_";
098        private static final String ORDERBY_PREFIX              = "EDIT_ORDERBY_";
099        private static final String DESC_PREFIX                 = "EDIT_DESC_";
100        private static final String GRANDTOTAL_PREFIX   = "EDIT_GRANDTOTAL_";
101        private static final String COMMON_PREFIX               = "EDIT_COMMON_";
102
103        private String  command                 = null;         // EW" 、アップロード="COPY|INSERT"
104        private String  gamenId                 = null;
105        private String  editName                = null;
106
107        private transient DBTableModel table            = null;         // 5.5.2.4 (2012/05/16) transient 定義追加
108        private transient DBEditConfig config           = null;         // 5.5.2.4 (2012/05/16) transient 定義追加
109        
110        private boolean orderOnly               = false; // 5.5.5.2 (2012/08/10)
111
112        /**
113         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
114         *
115         * @return      後続処理の指示(SKIP_BODY)
116         */
117        @Override
118        public int doStartTag() {
119                return(SKIP_BODY);                              // Body を評価しない
120        }
121
122        /**
123         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
124         *
125         * @og.rev 5.7.1.2 (2013/12/20) msg ⇒ errMsg 変更
126         *
127         * @return      後続処理の指示
128         */
129        @Override
130        public int doEndTag() {
131                debugPrint();
132
133                StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
134
135                // エディット情報をHTMLに変換して表示します。
136                // 表示に当たって、最後に発行されたQUERYのtableId、scopeをチェックした上で
137                // 表示するかを判断します。
138                if( "GET".equals( command ) ) {
139                        DBLastSql lastSql = (DBLastSql)getSessionAttribute( HybsSystem.DB_LAST_SQL_KEY );
140                        if( lastSql != null ) {
141                                if( !lastSql.isViewEditable() ) {
142                                        // この画面は、項目の並び替えはできません。
143                                        String rtn = "<b style=\"font-color:red;\">" + getResource().getLabel( "GEE0003" ) + "</b>";
144                                        jspPrint( rtn );
145                                }
146                                else if( lastSql.isGuiMatch( gamenId ) ) {
147                                        setScope( lastSql.getScope() );
148                                        table = (DBTableModel)getObject( lastSql.getTableId() );
149                                        if( table != null ) {
150                                                config = getUser().getEditConfig( gamenId, editName );
151                                                String viewClms = null;
152                                                if( config == null ) {
153                                                        viewClms = lastSql.getViewClmNames();
154                                                        config = new DBEditConfig();
155                                                }
156                                                else {
157//                                                      viewClms = config.getViewClms();
158                                                        viewClms = config.getViewClms( lastSql.getOrgClmNames() );
159                                                }
160                                                buf.append( makeEditTable( viewClms ) );
161                                        }
162                                }
163                        }
164                }
165                // エディット情報を保存します。
166                else if( "SET".equals( command ) ) {
167                        if( editName == null || editName.length() == 0 ) {
168//                              String msg = "エディット名が指定されていません。";
169//                              throw new HybsSystemException( msg );
170                                String errMsg = "エディット名が指定されていません。";
171                                throw new HybsSystemException( errMsg );        // 5.7.1.2 (2013/12/20) msg ⇒ errMsg 変更
172                        }
173                        // 5.9.18.1 (2017/03/24) ADD 編集名の共通判別対応
174                        String isCommon         = getRequest().getParameter( COMMON_PREFIX );
175                        // 共通以外で、頭文字が'*'でない場合
176                        if( !"1".equals( isCommon ) && '*' == editName.charAt(0) ){
177                                String errMsg = "共通以外の場合は、編集名に頭文字に*を使用できません。";
178                                throw new HybsSystemException(errMsg);
179                        }
180                        saveEditConfig();
181                }
182                // エディット情報を削除します。
183                else if( "DELETE".equals( command ) ) {
184                        if( editName == null || editName.length() == 0 ) {
185//                              String msg = "エディット名が指定されていません。";
186//                              throw new HybsSystemException( msg );
187                                String errMsg = "エディット名が指定されていません。";
188                                throw new HybsSystemException( errMsg );        // 5.7.1.2 (2013/12/20) msg ⇒ errMsg 変更
189                        }
190                        deleteEditConfig();
191                }
192                // 指定された画面IDに対するエディット情報の一覧(プルダウン)を表示します。
193                else if( "LIST".equals( command ) ) {
194                        DBEditConfig[] configs = getUser().getEditConfigs( gamenId );
195                        if( configs != null && configs.length > 0 ) {
196                                buf.append( getEditSelect( configs ) ).append( HybsSystem.CR );
197                        }
198                }
199
200                jspPrint( buf.toString() );
201
202                return(EVAL_PAGE);
203        }
204
205        /**
206         * タグリブオブジェクトをリリースします。
207         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
208         *
209         * @og.rev 5.5.5.2 (2012/08/10) orderOnly対応
210         */
211        @Override
212        protected void release2() {
213                super.release2();
214                command = "GET";
215                gamenId = null;
216                editName = null;
217                table = null;
218                config = null;
219                orderOnly               = false; //5.5.5.2 (2012/08/10)
220        }
221
222        /**
223         * エディット情報をHTMLに変換して表示します。
224         *
225         * @og.rev 5.4.2.0 (2011/12/01) 入替え対象のカラム列でのみスクロールが表示されるように対応します。
226         * @og.rev 5.5.5.2 (2012/08/10) orderOnly対応
227         *
228         * @param viewClms 表示カラム(カンマ区切り)
229         *
230         * @return エディット情報のHTML
231         */
232        private String makeEditTable( final String viewClms ) {
233                StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
234
235                boolean useSum = getUseSum( viewClms );
236                String[] viewGroups = StringUtil.csv2Array( viewClms, '|' );
237                buf.append( "<input type=\"hidden\" name=\"viewClms\" id=\"viewClms\" value=\"" + viewClms + "\"/>" );
238                buf.append( "<div />" );
239                buf.append( "<div style=\"float:left;\">" );
240                buf.append( makeLabelRow( useSum ) );
241                buf.append( "</div>" );
242                buf.append( "<div id=\"clmLayer\" style=\" float:left; width: 670px;overflow-x:scroll;\">" );
243                for( int i=0; i<viewGroups.length; i++ ) {
244                        if( i > 0 ) {
245                                buf.append( makeSeparateRow( useSum ) );
246                        }
247                        buf.append( "<table class=\"clmGroup\" style=\"float:left;\"><tr>" );
248                        String[] clms = StringUtil.csv2Array( viewGroups[i] );
249                        for( int j=0; j<clms.length; j++ ) {
250                                String clm = ( !clms[j].startsWith( "!" ) ? clms[j] : clms[j].substring( 1 ) );
251                                if( "rowCount".equals( clm ) ) { continue; }
252                                boolean isView = ( !clms[j].startsWith( "!" ) ? true : false );
253                                buf.append( makeColumnRow( clm, isView, useSum, config ) );
254                        }
255                        buf.append( "</tr></table>" );
256                }
257                buf.append( "</div>" );
258
259                String grandTotalLabel = "<b>" + getDBColumn( GRANDTOTAL_PREFIX + "LABEL" ).getLongLabel() + ":</b>";
260                buf.append( "<div style=\"clear:both;\">" );
261                buf.append( "<table>" );
262//              buf.append( makeCheckbox( GRANDTOTAL_PREFIX, config.useGrandTotal(), "h", grandTotalLabel ) );
263                buf.append( makeCheckbox( GRANDTOTAL_PREFIX, config.useGrandTotal(), "h", grandTotalLabel, orderOnly ) ); // 5.5.5.2 (2012/08/10)
264                buf.append( "</table>" );
265                buf.append( "</div>" );
266
267                return buf.toString();
268        }
269
270        /**
271         * エディット情報のヘッダー(ラベル行)のHTMLを生成します。
272         *
273         * @og.rev 5.4.2.0 (2011/12/01) 表示項目の全チェック機能を追加
274         * @og.rev 5.5.5.2 (2012/08/10) orderOnly対応
275         *
276         * @param useSum 集計対象のカラム(=NUMBER型)が存在しているか
277         *
278         * @return エディット情報のヘッダー(ラベル行)のHTML
279         */
280        private String makeLabelRow( final boolean useSum ) {
281                StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_SMALL );
282                String commonLabel = "<b>" + getDBColumn( COMMON_PREFIX + "LABEL" ).getLongLabel() + ":</b>";
283                String canEditCommon = HybsSystem.sys( "EDIT_COMMON_ROLES" );
284
285                String groupLabel = "<b>" + getDBColumn( GROUP_PREFIX + "LABEL" ).getLongLabel() + "</b>";
286                groupLabel += "<img id=\"groupBtn\" src=\"" + HybsSystem.sys( "JSP" ) + "/image/ball-green.gif\" />";
287
288                buf.append( "<table><tr>" );
289                buf.append( "<td style=\"margin:0px; padding:0px;\"><table>" );
290                if( getUser().isAccess( canEditCommon ) ) {
291//                      buf.append( makeCheckbox( COMMON_PREFIX, config.isCommon(), "h", commonLabel ) );
292                        buf.append( makeCheckbox( COMMON_PREFIX, config.isCommon(), "h", commonLabel, orderOnly ) ); // 5.5.5.2 (2012/08/10)
293                }
294                else {
295                        buf.append( makeLabel   ( commonLabel ) );
296                }
297//              buf.append( makeLabel   ( VIEW_PREFIX           + "LABEL" ) );
298                String viewLabel = "<b>" + getDBColumn( VIEW_PREFIX + "LABEL" ).getLongLabel() + ":</b>";
299//              buf.append( makeCheckbox( "VIEW_ALL_CHECK", true, "h", viewLabel ) );
300                buf.append( makeCheckbox( "VIEW_ALL_CHECK", true, "h", viewLabel, orderOnly ) ); // 5.5.5.2 (2012/08/10)
301                if( useSum ) {
302                        buf.append( makeLabel   ( SUM_PREFIX            + "LABEL" ) );
303                }
304                buf.append( makeCell    ( groupLabel, "h" ) );
305                buf.append( makeLabel   ( SUBTOTAL_PREFIX       + "LABEL" ) );
306                buf.append( makeLabel   ( TOTAL_PREFIX          + "LABEL" ) );
307                buf.append( makeLabel   ( ORDERBY_PREFIX        + "LABEL" ) );
308                buf.append( makeLabel   ( DESC_PREFIX           + "LABEL" ) );
309                buf.append( "</table></td>" );
310                buf.append( "</tr></table>" );
311                return buf.toString();
312        }
313
314        /**
315         * エディット情報のカラム列のHTMLを生成します。
316         * 
317         * @og.rev 5.5.5.2 (2012/08/10) orderOnly対応
318         * @og.rev 5.7.5.2 (2014/04/11) 降順はorderOnlyに関わらず編集可能にする
319         *
320         * @param clm カラム
321         * @param isView 表示対象かどうか
322         * @param useSum 集計対象のカラム(=NUMBER型)が存在しているか
323         * @param config エディット設定オブジェクト
324         *
325         * @return エディット情報のカラム列のHTMLを生成します。
326         */
327        private String makeColumnRow( final String clm, final boolean isView, final boolean useSum, final DBEditConfig config ) {
328                StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_SMALL );
329
330                int clmNo = table.getColumnNo( clm, false  );
331                DBColumn column = ( clmNo < 0 ? getDBColumn( clm ) : table.getDBColumn( clmNo ) );
332                buf.append( "<td name=\"" ).append( clm ).append( "\" class=\"sortItem\" style=\"margin:0px; padding:0px;\">" );
333                buf.append( "<table>" );
334                buf.append( makeLabel   ( column.getLongLabel() ) );
335//              buf.append( makeCheckbox( VIEW_PREFIX                   + clm, isView                                           , "0", null ) );
336                buf.append( makeCheckbox( VIEW_PREFIX                   + clm, isView                                           , "0", null, orderOnly ) ); // 5.5.5.2 (2012/08/10)
337                if( useSum ) {
338                        boolean isSumClm = isNumberClm( clm );
339//                      buf.append( makeCheckbox( SUM_PREFIX            + clm, config.isSumClm( clm )           , "1", isSumClm , null ) );
340                        buf.append( makeCheckbox( SUM_PREFIX            + clm, config.isSumClm( clm )           , "1", isSumClm , null, orderOnly ) ); // 5.5.5.2 (2012/08/10)
341                }
342//              buf.append( makeCheckbox( GROUP_PREFIX          + clm, config.isGroupClm( clm )         , "0", null ) );
343//              buf.append( makeCheckbox( SUBTOTAL_PREFIX       + clm, config.isSubTotalClm( clm )      , "1", null ) );
344//              buf.append( makeCheckbox( TOTAL_PREFIX          + clm, config.isTotalClm( clm )         , "0", null ) );
345//              buf.append( makeInput   ( ORDERBY_PREFIX                + clm, config.getOrder( clm )           , "1", null ) );
346//              buf.append( makeCheckbox( DESC_PREFIX                   + clm, config.isOrderByDesc( clm )      , "0", null ) );
347                buf.append( makeCheckbox( GROUP_PREFIX          + clm, config.isGroupClm( clm )         , "0", null, orderOnly ) ); // 5.5.5.2 (2012/08/10)
348                buf.append( makeCheckbox( SUBTOTAL_PREFIX       + clm, config.isSubTotalClm( clm )      , "1", null, orderOnly ) ); // 5.5.5.2 (2012/08/10)
349                buf.append( makeCheckbox( TOTAL_PREFIX          + clm, config.isTotalClm( clm )         , "0", null, orderOnly ) ); // 5.5.5.2 (2012/08/10)
350                buf.append( makeInput   ( ORDERBY_PREFIX                + clm, config.getOrder( clm )           , "1", null ) );
351//              buf.append( makeCheckbox( DESC_PREFIX                   + clm, config.isOrderByDesc( clm )      , "0", null, orderOnly ) ); // 5.5.5.2 (2012/08/10)
352                buf.append( makeCheckbox( DESC_PREFIX                   + clm, config.isOrderByDesc( clm )      , "0", null, false ) ); // 5.7.5.1 (2014/04/11)
353                buf.append( "</table>" );
354                buf.append( "</td>" );
355
356                return buf.toString();
357        }
358
359        /**
360         * チェックボックスのHTML文字列を生成します。
361         * 生成したHTMLは以下のようになります。
362         * 例)&lt;tr&gt;&lt;td class="row_[bgCnt]" ...&gt;[prefix]&lt;input type="checkbox" name="[clm]" ... /&gt;&lt;/td&gt;&lt;/tr&gt;
363         *
364         * @param clm カラム
365         * @param checked 初期チェックするかどうか
366         * @param bgCnt 背景色ゼブラカラーの指定("0"or"1"or"h")
367         * @param prefix チェックボックスのタグの前に挿入するHTML文字列
368         * @param readonly リードオンリー
369         * 
370         * @og.rev 5.5.5.2 (2012/08/10) readOnly追加
371         *
372         * @return チェックボックスのHMTL文字列
373         */
374//      private String makeCheckbox( final String clm, final boolean checked, final String bgCnt, final String prefix ) {
375        private String makeCheckbox( final String clm, final boolean checked, final String bgCnt, final String prefix, final boolean readonly ) {
376                return makeCheckbox( clm, checked, bgCnt, true, prefix, readonly );
377        }
378
379        /**
380         * チェックボックスのHTML文字列を生成します。
381         * 生成したHTMLは以下のようになります。
382         * 例)&lt;tr&gt;&lt;td class="row_[bgCnt]" ...&gt;[prefix]&lt;input type="checkbox" name="[clm]" ... /&gt;&lt;/td&gt;&lt;/tr&gt;
383         *
384         * @param clm カラム
385         * @param checked 初期チェックするかどうか
386         * @param bgCnt 背景色ゼブラカラーの指定("0"or"1"or"h")
387         * @param isChbox チェックボックスを生成するかどうか(falseの場合、チェックボックスのinputタグは生成されません)
388         * @param prefix チェックボックスのタグの前に挿入するHTML文字列
389         * @param readonly リードオンリー
390         * 
391         * @og.rev 5.5.5.2 (2012/08/10) readOnly追加
392         *
393         * @return チェックボックスのHMTL文字列
394         */
395//      private String makeCheckbox( final String clm, final boolean checked, final String bgCnt, final boolean isChbox, final String prefix ) {
396        private String makeCheckbox( final String clm, final boolean checked, final String bgCnt, final boolean isChbox, final String prefix, final boolean readonly ) {
397                if( isChbox ) {
398                        String suffix = "";
399                        TagBuffer tag = new TagBuffer( "input" );
400                        tag.add( "type", "checkbox" );
401                        tag.add( "name", clm );
402                        tag.add( "value", "1" );
403                        if( checked ) {
404                                tag.add( "checked", "checked" );
405                        }
406                        if( readonly ){ // 5.5.5.2 (2012/08/10)
407                                tag.add( "disabled", "disabled" );
408                                if( checked ){
409                                        TagBuffer tag2 = new TagBuffer( "input" );
410                                        tag2.add( "type", "hidden" );
411                                        tag2.add( "name", clm );
412                                        tag2.add( "value", "1" );
413                                        suffix += tag2.makeTag();
414                                }
415                                
416                        }
417//                      return makeCell( ( prefix == null ? "" : prefix ) + tag.makeTag(), bgCnt );
418                        return makeCell( ( prefix == null ? "" : prefix ) + tag.makeTag() + suffix, bgCnt ); // 5.5.5.2 (2012/08/10)
419                }
420                else {
421                        return makeCell( ( prefix == null ? "" : prefix ) + "&nbsp;", bgCnt );
422                }
423        }
424
425        /**
426         * テキスト入力HTML文字列を生成します。
427         * 生成したHTMLは以下のようになります。
428         * 例)&lt;tr&gt;&lt;td class="row_[bgCnt]" ...&gt;[prefix]&lt;input type="text" name="[clm]" ... /&gt;&lt;/td&gt;&lt;/tr&gt;
429         *
430         * @param clm カラム
431         * @param value 初期チェックするかどうか
432         * @param bgCnt 背景色ゼブラカラーの指定("0"or"1"or"h")
433         * @param prefix チェックボックスのタグの前に挿入するHTML文字列
434         *
435         * @return チェックボックスのHMTL文字列
436         */
437        private String makeInput( final String clm, final String value, final String bgCnt, final String prefix ) {
438                TagBuffer tag = new TagBuffer( "input" );
439                tag.add( "type", "text" );
440                tag.add( "name", clm );
441                tag.add( "value", value );
442                tag.add( "style", "width: 10px; font-size:10px;" );
443                tag.add( "maxlength", "2" );
444                tag.add( "class", "S9" );
445
446                return makeCell( ( prefix == null ? "" : prefix ) + tag.makeTag(), bgCnt );
447        }
448
449        /**
450         * 左右分割されている際の分割列のHTML文字列を生成します。
451         *
452         * @param useSum 集計対象のカラム(=NUMBER型)が存在しているか
453         *
454         * @return チェックボックスのHMTL文字列
455         */
456        private String makeSeparateRow( final boolean useSum ) {
457                StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_SMALL );
458
459                buf.append( "<table style=\"float:left;\"><tr>" );
460                buf.append( "<td style=\"margin:0px; padding:0px;\"><table>" );
461                buf.append( makeCell( "&nbsp", "h" ) );             // ラベル
462                buf.append( makeCell( "&nbsp", "h" ) );             // 表示
463                if( useSum ) {
464                        buf.append( makeCell( "&nbsp", "h" ) );             // 集計項目
465                }
466                buf.append( makeCell( "&nbsp", "h" ) ); // 集計キー
467                buf.append( makeCell( "&nbsp", "h" ) );     // 小計キー
468                buf.append( makeCell( "&nbsp", "h" ) ); // 合計キー
469                buf.append( makeCell( "&nbsp", "h" ) ); // 表示順
470                buf.append( makeCell( "&nbsp", "h" ) ); // 昇順・降順
471                buf.append( "</table></td>");
472                buf.append( "</tr></table>" );
473
474                return buf.toString();
475        }
476
477        /**
478         * ラベルのHTML文字列を生成します。
479         *
480         * @param clm カラム
481         *
482         * @return ラベルのHTML文字列
483         */
484        private String makeLabel( final String clm ) {
485                return makeCell( getDBColumn( clm ).getLongLabel(), "h" );
486        }
487
488        /**
489         * セルのHTML文字列を生成します。
490         *
491         * @param body tdタグ内のHTML文字列
492         * @param bgCnt 背景色ゼブラカラーの指定("0"or"1"or"h")
493         *
494         * @return セルのHTML文字列
495         */
496        private String makeCell( final String body, final String bgCnt ) {
497                return "<tr><td align=\"center\" style=\"height:22px;\" class=\"row_" + bgCnt + "\">" + body + "</td></tr>";
498        }
499
500        /**
501         * このエディット設定で集計対象のカラム(=NUMBER型)が存在しているかを返します。
502         *
503         * @param viewClms カラム
504         *
505         * @return 集計対象のカラム(=NUMBER型)が存在しているか
506         */
507        private boolean getUseSum( final String viewClms ) {
508                if( viewClms == null ) { return false; }
509
510                boolean rtn = false;
511                String[] clms = StringUtil.csv2Array( viewClms.replace( '|', ',' ) );
512                for( int j=0; j<clms.length; j++ ) {
513                        String clm = ( !clms[j].startsWith( "!" ) ? clms[j] : clms[j].substring( 1 ) );
514                        rtn = isNumberClm( clm );
515                        if( rtn ) { break; }
516                }
517                return rtn;
518        }
519
520        /**
521         * 引数のカラムがNUMBER型かどうかをチェックします。
522         *
523         * @param clm カラム
524         *
525         * @return NUMBER型かどうか
526         */
527        private boolean isNumberClm( final String clm ) {
528                if( clm == null ) { return false; }
529
530                int no = table.getColumnNo( clm, false );
531                if( no >= 0 ) {
532                        DBColumn dbClm = table.getDBColumn( table.getColumnNo( clm ) );
533                        if( dbClm != null ) {
534                                if( "NUMBER".equals( dbClm.getClassName()) ) {
535                                        return true;
536                                }
537                        }
538                }
539                return false;
540        }
541
542        /**
543         * エディット設定情報を保存します。
544         *
545         * @og.rev 5.9.18.1 (2017/03/24) 共通の編集名対応
546         */
547        private void saveEditConfig() {
548                String viewClms         = getRequest().getParameter( "viewClms" );
549                String sumClms          = getColumns( SUM_PREFIX );
550                String groupClms        = getColumns( GROUP_PREFIX );
551                String subTotalClms = getColumns( SUBTOTAL_PREFIX );
552                String totalClms        = getColumns( TOTAL_PREFIX );
553                String useGrandTotal= getRequest().getParameter( GRANDTOTAL_PREFIX );
554                String orderByClms      = getOrderByColumns();
555                String isCommon         = getRequest().getParameter( COMMON_PREFIX );
556
557                // 5.9.18.1 (2017/03/24) ADD 編集名の共通判別対応
558                // 共通で、編集名の頭に「*」が無い場合
559                if("1".equals( isCommon ) && !('*' == editName.charAt( 0 ))){
560                        // 編集名の頭に「*」を付与 
561                        editName        = "*"+editName;
562                }
563                // 編集名をリクエストスコープに設定
564                setRequestAttribute("regEditName", editName);
565                
566                DBEditConfig config
567                        = new DBEditConfig( editName, viewClms, sumClms, groupClms
568                                                                , subTotalClms, totalClms, useGrandTotal, orderByClms, isCommon );
569
570                getUser().addEditConfig( gamenId, editName, config );
571        }
572
573        /**
574         * エディット設定情報を削除します。
575         */
576        private void deleteEditConfig() {
577                getUser().deleteEditConfig( gamenId, editName );
578        }
579
580        /**
581         * パラメーターから引数のプレフィックスをキーに、チェックされたカラム一覧(カンマ区切り)を返します。
582         *
583         * @param prefixKey 各キーの取得するためのプレフィックス
584         *
585         * @return カラム一覧(カンマ区切り)
586         */
587        private String getColumns( final String prefixKey ) {
588                StringBuilder buf = new StringBuilder();
589
590                Enumeration<?> enume = getParameterNames();
591                while( enume.hasMoreElements() ) {
592                        String key = (String)(enume.nextElement());
593                        if( key.startsWith( prefixKey ) ) {
594                                String val = getRequest().getParameter( key );
595                                if( "1".equals( val ) ) {
596                                        String clm = key.substring( prefixKey.length() );
597                                        if( buf.length() > 0 ) { buf.append( "," ); }
598                                        buf.append( clm );
599                                }
600                        }
601                }
602
603                return buf.toString();
604        }
605
606        /**
607         * 表示順のカラム一覧(カンマ区切り)を返します。
608         *
609         * @return 表示順のカラム一覧(カンマ区切り)
610         */
611        private String getOrderByColumns() {
612                Enumeration<?> enume = getParameterNames();
613                List<Integer> orderNo = new ArrayList<Integer>();
614                Map<Integer,String> orderClm = new HashMap<Integer,String>();
615                while( enume.hasMoreElements() ) {
616                        String key = (String)(enume.nextElement());
617                        if( key.startsWith( ORDERBY_PREFIX ) ) {
618                                String val = getRequest().getParameter( key );
619                                if( val != null && val.length() > 0 ) {
620                                        String clm = key.substring( ORDERBY_PREFIX.length() );
621                                        String desc = getRequest().getParameter( DESC_PREFIX + clm );
622                                        if( "1".equals( desc ) ) {
623                                                clm = "!"  + clm;
624                                        }
625                                        // 数字項目以外が入力された場合は無視
626                                        Integer odno = null;
627                                        try {
628                                                odno = Integer.valueOf( val );
629                                        }
630                                        catch ( NumberFormatException ex ) {
631                                                continue;
632                                        }
633                                        String str = orderClm.get( odno );
634                                        // 同じ番号の場合でも重ならないように振り直しする。
635                                        while( str != null ) {
636                                                odno = Integer.valueOf( odno.intValue() + 1 );
637                                                str = orderClm.get( odno );
638                                        }
639                                        orderClm.put( odno, clm );
640                                        orderNo.add( odno );
641                                }
642                        }
643                }
644
645                Collections.sort( orderNo );
646
647                StringBuilder buf = new StringBuilder();
648                for( Integer i : orderNo ) {
649                        if( buf.length() > 0 ) { buf.append( "," ); }
650                        String clm = orderClm.get( i );
651                        buf.append( clm );
652                }
653
654                return buf.toString();
655        }
656
657        /**
658         * エディット設定一覧のプルダウンメニューを作成します。
659         *
660         * @param       configs DBEditConfig配列
661         *
662         * @return      エディット一覧のプルダウン
663         */
664        private String getEditSelect( final DBEditConfig[] configs ) {
665                DBColumn column = getDBColumn( "editName" );
666
667                StringBuilder buf = new StringBuilder();
668                buf.append( "<span class=\"label editName\">" )
669                        .append( column.getLongLabel() )
670                        .append( ":</span><span class=\"editName\">" )
671                        .append( "<select name=\"editName\">" )
672                        .append( "<option />" );
673                for( DBEditConfig config : configs ) {
674                        String name = config.getEditName();
675                        buf.append( "<option value=\"" ).append( name ).append( "\"" );
676                        if( config.isCommon() ) {
677                                buf.append( " class=\"commonEdit\"" );
678                        }
679                        buf.append( "\">" );
680                        buf.append( name ).append( "</option>" );
681                }
682                buf.append( "</select></span>" );
683                return buf.toString();
684        }
685
686        /**
687         * 【TAG】command を指定します。
688         *
689         * @og.tag
690         * command を指定します。
691         * [GET/LIST/SET/DELETE]のみが設定可能です。それ以外の場合、何も処理されません。
692         *
693         * @param       cmd コマンド[GET/LIST/SET/DELETE]
694         */
695        public void setCommand( final String cmd ) {
696                command = nval( getRequestParameter( cmd ),command );
697        }
698
699        /**
700         * 【TAG】画面ID を指定します。
701         *
702         * @og.tag
703         * 画面ID を指定します。
704         *
705         * @param       key 画面ID
706         */
707        public void setGamenId( final String key ) {
708                gamenId = nval( getRequestParameter( key ),gamenId );
709        }
710
711        /**
712         * 【TAG】エディット名 を指定します。
713         *
714         * @og.tag
715         * エディット名 を指定します。
716         * commandがSETまたはDELETEの場合は必須です。
717         * commandがGETまたはLISTの場合は無効です。
718         *
719         * @param       name エディット名
720         */
721        public void setEditName( final String name ) {
722                editName = nval( getRequestParameter( name ),editName );
723        }
724        
725        /**
726         * 【TAG】チェックボックスのリードオンリー化を行います
727         *
728         * @og.tag
729         * 順番の入れ替えと、表示順の設定のみを行う場合にtrueにします。
730         * 表示/非表示切替や、集計機能は利用できなくなります。
731         * (チェックボックスのリードオンリーはできないため、実際にはdisable+hiddenで出力しています)
732         *
733         * @og.rev 5.5.5.2 (2012/08/10) 新規追加
734         *
735         * @param   flag  [true:リードオンリー/それ以外:編集可]
736         */
737        public void setOrderOnly( final String flag ) {
738                orderOnly = nval( getRequestParameter( flag ),orderOnly );
739        }
740
741        /**
742         * このオブジェクトの文字列表現を返します。
743         * 基本的にデバッグ目的に使用します。
744         *
745         * @return このクラスの文字列表現
746         */
747        @Override
748        public String toString() {
749                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
750                                .println( "VERSION"             ,VERSION                )
751                                .println( "command"             ,command                )
752                                .println( "gamenId"             ,gamenId                )
753                                .println( "editName"    ,editName               )
754                                .println( "Other..."    ,getAttributes().getAttribute() )
755                                .fixForm().toString() ;
756        }
757}