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 org.opengion.hayabusa.common.HybsSystem;
019import org.opengion.hayabusa.html.ViewCrossTableParam;
020
021import static org.opengion.fukurou.util.StringUtil.nval ;
022
023import java.io.ObjectOutputStream;
024import java.io.ObjectInputStream;
025import java.io.IOException;
026
027/**
028 * viewタグの viewFormType が HTMLCrossTable の場合にパラメータを設定します。
029 *
030 * クロス集計を行う、ViewForm_HTMLCrossTable クラスに対して、各種パラメータを
031 * 設定します。
032 * パラメータが設定されていない場合は、ViewCrossTableParam の初期値が使用されます。
033 * (パラメータを使用するには、viewタグのuseParam 属性をtrueに設定する必要があります。)
034 *
035 * SELECT文は、CROSS集計機能を利用して求めます。そのときのフォーマットは、
036 * ヘッダー1..N,縦,横,計1..N になります。
037 * ヘッダー部は、複数指定できますが、デフォルトではヘッダーNがキーブレイクすると
038 * 合計用のヘッダーが挿入されます。また、ヘッダーは、前段と同じ値の場合は、表示しません。
039 * 合計は、複数並べることができますが、sumNumber で指定しておく必要があります。
040 *
041 * 各属性は、{@XXXX} 変数が使用できます。
042 * これは、ServletRequest から、XXXX をキーに値を取り出し,この変数に割り当てます。
043 * つまり、このXXXXをキーにリクエストすれば、この変数に値をセットすることができます。
044 *
045 * http://localhost/query.jsp?KEY1=VLA1&KEY2=VAL2
046 *
047 * のようなリクエストで、{@KEY1} とすれば、 VAL1 がセットされます。
048 *
049 * @og.formSample
050 * ●形式:<og:crossParam breakColumn="ZZZ" noGroupColumns="AAA,BBB" sumNumber="2" />
051 * ●body:なし
052 *
053 * ●Tag定義:
054 *   <og:crossParam
055 *       cubeXColumn        【TAG】CUBE計算の1つ目(X)カラムを指定します
056 *       cubeYColumn        【TAG】CUBE計算の2つ目(Y)カラムを指定します
057 *       sumNumber          【TAG】合計値のカラム数を設定します
058 *       breakColumn        【TAG】ブレークによりヘッダー部を出力させるカラム名をセットします(初期値:ヘッダーN)
059 *       noGroupColumns     【TAG】カラム値を前段と比較して同じ場合でも表示させるカラム名をセットします
060 *       shokeiLabel        【TAG】列小計のカラムに表示するラベルIDを指定します(初期値:空文字列)
061 *       gokeiLabel         【TAG】列合計のカラムに表示するラベルIDを指定します(初期値:空文字列)
062 *       cubeSortType       【TAG】CUBE Y の列ヘッダーのソート方式を指定します(初期値:LOAD)
063 *       gokeiSortDir       【TAG】合計行のソート有無とその方向[true:正方向/false:逆方向/null:ソートしない]を指定します(初期値:null)
064 *       useHeaderColumn    【TAG】ヘッダーカラムにレンデラー、エディターを適用するかを指定します(初期値:false)
065 *       useClassAdd        【TAG】各列情報のclass属性に、カラム名などを付与するかどうかを指定します(初期値:false)
066 *       firstClmGokei      【TAG】合計列をCUBEの先頭部分に出すかどうか[true/false]を指定します(初期値:false)
067 *       saveTableId        【TAG】クロス集計結果の DBTableModel をセーブするセッションキーワードを指定します
068 *       saveScope          【TAG】クロス集計結果の DBTableModel をセーブする scope を指定します
069 *       useHeaderResource  【TAG】ヘッダー表示にラベルリソースを適用するかどうかを指定します(初期値:false)
070 *       headerCodeColumn   【TAG】ヘッダー表示に利用するコードを持つカラムを指定します(初期値:空文字列)
071 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
072 *   />
073 *
074 * ●使用例
075 *     ViewFormTag の viewFormType が、HTMLCrossTable の場合に使用します。
076 *     useParam 属性を設定しておかないと、使用されません。
077 *     <og:view
078 *         viewFormType = "HTMLCrossTable"
079 *         command      = "{@command}"
080 *         startNo      = "0"
081 *         pageSize     = "20"
082 *         <b>useParam     = &quot;true&quot;</b>
083 *     &gt;
084 *         &lt;og:crossParam
085 *             breakColumn    = "ZZZ"       : ブレークによりヘッダー部を出力させるカラム名
086 *             noGroupColumns = "AAA,BBB"   : カラム値を前段と比較して同じ場合でも表示させるカラム名
087 *             cubeXColumn    = "CUBE_X"    : CUBE計算の1つ目(X)カラムを指定
088 *             cubeYColumn    = "CUBE_Y"    : CUBE計算の2つ目(Y)カラムを指定
089 *             shokeiLabel    = "SHOKEI"    : 列小計のカラムに表示するラベルID(初期値:SHOKEI)
090 *             gokeiLabel     = "GOKEI"     : 列合計のカラムに表示するラベルID(初期値:GOKEI)
091 *             sumNumber      = "2"         : 合計値のカラム数(初期値1)
092 *             cubeSortType   = "NUMBER"    : CUBE Y の列ヘッダーのソート方式を指定[STRING/NUMBER/LOAD]
093 *             gokeiSortDir   = "false"     : 合計行のソート有無とその方向(正方向/逆方向)を指定[true/false/null]
094 *             firstClmGokei  = "true"      : 合計列をCUBEの先頭部分に出すかどうかを指定[false/true/null]
095 *             useHeaderColumn= "true"      : ヘッダーカラムにレンデラー、エディターを適用するかどうかを指定[false/true/null]
096 *             saveTableId    = "DEFAULT"   : クロス集計結果の DBTableModel をセーブするセッションキーワードを指定
097 *             useClassAdd    = "true"      : String 各列情報のclass属性に、カラム名などを付与するかどうかを指定[false/true/null]
098 *        /&gt;
099 *     &lt;/og:view &gt;
100 *
101 * @og.group 画面表示
102 *
103 * @version  4.0
104 * @author       Kazuhiko Hasegawa
105 * @since    JDK5.0,
106 */
107public class ViewCrossParamTag extends ViewParamTag {
108        //* このプログラムのVERSION文字列を設定します。   {@value} */
109        private static final String VERSION = "5.5.5.0 (2012/07/28)" ;
110
111        private static final long serialVersionUID = 555020120728L ;
112
113        /**
114         * 【TAG】ブレークによりヘッダー部を出力させるカラム名をセットします(初期値:ヘッダーN)。
115         *
116         * @og.tag
117         * CROSS集計で求めたフォーマットは、『ヘッダー1..N,縦,横,計1..N 』です。
118         * ヘッダー部は、複数指定できますが、デフォルトではヘッダーNがキーブレイクすると
119         * 合計用のヘッダーが挿入されます。
120         * このヘッダーNそのものが、集計フィールドでなく、単なる属性の場合は、
121         * キーブレイクして欲しくない為、breakColumn="ヘッダーN-1" を指定します。
122         * 初期値は、"ヘッダーN" です。
123         *
124         * @param       clm ブレークさせるカラム名
125         */
126        public void setBreakColumn( final String clm ) {
127                putParam( ViewCrossTableParam.BREAK_COLUMN_KEY,
128                                  nval( getRequestParameter( clm ),null ) );
129        }
130
131        /**
132         * 【TAG】カラム値を前段と比較して同じ場合でも表示させるカラム名をセットします。
133         *
134         * @og.tag
135         * CROSS集計で求めたフォーマットは、『ヘッダー1..N,縦,横,計1..N 』です。
136         * ヘッダー部は、キーブレイクする都度、ヘッダーを出力します。それまでは、
137         * 各ヘッダーの値が、前段(同一カラムの先の値)と同じ場合は、空白にします。
138         * こうする事で、値のグループ化が一目で判ります。(初期設定)
139         * このヘッダーが、集計フィールドでなく、単なる属性の場合は、
140         * 空白ではなく、値として表示したい為、グループ化しない事を指定します。
141         *
142         * @param       clms グループ化(空白化)したくないカラム(カンマ区切り)
143         */
144        public void setNoGroupColumns( final String clms ) {
145                putParam( ViewCrossTableParam.NO_GROUP_COLUMNS_KEY,
146                                  nval( getRequestParameter( clms ),null ) );
147        }
148
149        /**
150         * 【TAG】合計値のカラム数を設定します(初期値:1)。
151         *
152         * @og.tag
153         * CROSS集計で求めたフォーマットは、『ヘッダー1..N,縦,横,計1..N 』です。
154         *  合計は、複数並べることができますが、sumNumber で指定しておく必要があります。
155         * 初期値は、1 です。
156         *
157         * @param       no 合計値のカラム数(初期値1)
158         */
159        public void setSumNumber( final String no ) {
160                putParam( ViewCrossTableParam.SUM_NUMBER_KEY,
161                                  nval( getRequestParameter( no ),"1" ) );
162        }
163
164        /**
165         * 【TAG】列小計のカラムに表示するラベルIDを指定します(初期値:空文字列)。
166         *
167         * @og.tag
168         * 各列の小計のラベルIDを登録します。登録する文字列は、ラベルリソースに
169         * 定義しておいて下さい。
170         * 初期値は、空文字列("")です。
171         *
172         * @og.rev 3.7.1.1 (2005/05/31) 初期値を "SHOKEI" に設定します。
173         *
174         * @param       id 列小計のカラムに表示するラベルID
175         */
176        public void setShokeiLabel( final String id ) {
177                String label = nval( getRequestParameter( id ),"SHOKEI" );
178                putParam( ViewCrossTableParam.SHOKEI_LABEL_KEY, getLabel( label ) );
179        }
180
181        /**
182         * 【TAG】列合計のカラムに表示するラベルIDを指定します(初期値:空文字列)。
183         *
184         * @og.tag
185         * 各列の合計のラベルIDを登録します。登録する文字列は、ラベルリソースに
186         * 定義しておいて下さい。
187         * 初期値は、空文字列("")です。
188         *
189         * @og.rev 3.7.1.1 (2005/05/31) 初期値を "GOKEI" に設定します。
190         *
191         * @param       id 列合計のカラムに表示するラベルID
192         */
193        public void setGokeiLabel( final String id ) {
194                String label = nval( getRequestParameter( id ),"GOKEI" );
195                putParam( ViewCrossTableParam.GOKEI_LABEL_KEY, getLabel( label ) );
196        }
197
198        /**
199         * 【TAG】CUBE計算の1つ目(X)カラムを指定します。
200         *
201         * @og.tag
202         * 列方向のキーとなるカラム名を指定します。
203         * 初期値は、互換性の関係より、sumNumber より逆計算します。
204         *
205         * @og.rev 3.5.5.9 (2004/06/07) 新規追加
206         *
207         * @param       cubeX 列合計のカラムに表示するラベルID
208         */
209        public void setCubeXColumn( final String cubeX ) {
210                putParam( ViewCrossTableParam.CUBE_X_COLUMN_KEY,
211                                  nval( getRequestParameter( cubeX ),null ) );
212        }
213
214        /**
215         * 【TAG】CUBE計算の2つ目(Y)カラムを指定します。
216         *
217         * @og.tag
218         * 行方向のキーとなるカラム名を指定します。
219         * 初期値は、互換性の関係より、sumNumber より逆計算します。
220         *
221         * @og.rev 3.5.5.9 (2004/06/07) 新規追加
222         *
223         * @param       cubeY 列合計のカラムに表示するラベルID
224         */
225        public void setCubeYColumn( final String cubeY ) {
226                putParam( ViewCrossTableParam.CUBE_Y_COLUMN_KEY,
227                                  nval( getRequestParameter( cubeY ),null ) );
228        }
229
230        /**
231         * 【TAG】CUBE Y の列ヘッダーのソート方式を指定します(初期値:LOAD)。
232         *
233         * @og.tag
234         * CUBEのヘッダーに対応するカラム列をソート表示する場合の方式を指定します。
235         * 種類として、STRING,NUMBER,LOAD,があります。
236         * 初期値(指定無し)は、LOAD(取り込み順にセット)です。
237         *
238         * @og.rev 3.5.6.3 (2004/07/12) 新規追加
239         *
240         * @param       cubeSortType CUBE Y の列ヘッダーのソート方式[STRING,NUMBER,LOAD]
241         */
242        public void setCubeSortType( final String cubeSortType ) {
243                putParam( ViewCrossTableParam.CUBE_SORT_TYPE_KEY,
244                                  nval( getRequestParameter( cubeSortType ),null ) );
245        }
246
247        /**
248         * 【TAG】合計行のソート有無とその方向[true:正方向/false:逆方向/null:ソートしない]を指定します(初期値:null)。
249         *
250         * @og.tag
251         * 最も最後の合計カラムにソートを行うかどうか、その時の方向を指定します。
252         * true/false 以外の文字列では、ソートを行いません。trueは、正方向(昇順)で、
253         * falseが逆方向(降順)になります。
254         * 初期値(指定無し)は、ソートしない(null)です。
255         *
256         * @og.rev 3.5.6.3 (2004/07/12) 新規追加
257         *
258         * @param       gokeiSortDir 合計行のソート有無とその方向[true:正方向/false:逆方向/null:ソートしない]
259         */
260        public void setGokeiSortDir( final String gokeiSortDir ) {
261                putParam( ViewCrossTableParam.GOKEI_SORT_DIR_KEY,
262                                  nval( getRequestParameter( gokeiSortDir ),null ) );
263        }
264
265        /**
266         * 【TAG】合計列をCUBEの先頭部分に出すかどうか[true/false]を指定します(初期値:false)。
267         *
268         * @og.tag
269         * 合計列を最終列に出力するか、CUBEの先頭列に出力するかを指定します。
270         * trueが指定された場合はCUBEの先頭列に出力します。
271         * 初期値(false)は合計列を最終列に出力します。
272         *
273         * @og.rev 5.0.0.3 (2009/09/22) 新規追加
274         *
275         * @param       firstClmGokei   合計列をCUBEの出力場所[true:先頭列に出力/false:最終列に出力]
276         */
277        public void setFirstClmGokei( final String firstClmGokei ) {
278                putParam( ViewCrossTableParam.FIRST_CLM_GOKEI_KEY,
279                                  nval( getRequestParameter( firstClmGokei ),"false" ) );
280        }
281
282        /**
283         * 【TAG】ヘッダーカラムにレンデラー、エディターを適用するかを指定します(初期値:false)。
284         *
285         * @og.tag
286         * ヘッダーカラムにレンデラー、エディターを適用するかを指定します。
287         * trueが指定された場合は、ヘッダー部分の値そのものをカラム名として扱います。
288         * リソースが存在しない場合は、ラベルのみを各カラムの値で置き換えます。
289         * 初期値(指定無し)は、レンデラー、エディターを適用しない(false)です。
290         *
291         * @og.rev 4.0.0.0 (2007/11/27) 新規追加
292         * @og.rev 5.2.2.0 (2010/11/01) キーに、ViewCrossTableParam.USE_HEADER_COLUMN を使用するように修正
293         *
294         * @param       useHeaderColumn ヘッダーカラムにレンデラー、エディターを適用するかどうか
295         */
296        public void setUseHeaderColumn( final String useHeaderColumn ) {
297                putParam( ViewCrossTableParam.USE_HEADER_COLUMN,
298                                  nval( getRequestParameter( useHeaderColumn ),"false" ) );
299        }
300
301        /**
302         * 【TAG】各列情報のclass属性に、カラム名などを付与するかどうかを指定します(初期値:false)。
303         *
304         * @og.tag
305         * 列情報の集計列に対して、class 属性を付与するかどうかを指定します。
306         * class属性は、その列のオリジナルの属性名と、ラベル名の文字列を設定します。
307         * 例えば、集計行の計カラムが複数ある場合は、それぞれに色を指定して、ゼブラ模様を
308         * 設定できます。また、ラベル(表示ヘッダー)も設定されるので、特別な列のみ指定することも
309         * 可能になります。
310         * ※ 特殊対応:cssなどで指定できるIDやCLASS属性は、先頭文字が数字の場合は、
311         * 無効になります。(つまり、効きません。)
312         * 表示ヘッダーは、年月や、社員番号(数字)などのケースもあります。そこで、先頭が数字の
313         * 場合は、"x"(小文字のx)を自動的に頭に追加します。この処理は、ViewForm_HTMLCrossTable
314         * で行います。
315         *
316         * @og.rev 5.2.2.0 (2010/11/01) 新規追加
317         *
318         * @param       useClassAdd     各列情報のclass属性に、カラム名などを付与するかどうか
319         */
320        public void setUseClassAdd( final String useClassAdd ) {
321                putParam( ViewCrossTableParam.USE_CLASS_ADD,
322                                  nval( getRequestParameter( useClassAdd ),"false" ) );
323        }
324
325        /**
326         * 【TAG】クロス集計結果の DBTableModel をセーブするセッションキーワードを指定します。
327         *
328         * @og.tag
329         * 検索のみの場合は、何も設定しません。EXCEL等外部にクロス集計の形で
330         * 取り出したい場合に、設定します。
331         * "DEFAULT" という文字列を指定すると、内部では、HybsSystem.TBL_MDL_KEY が
332         * 設定されます。(DEFAULT という文字列に設定されるわけではありません。)
333         * なお、DEFAULT を使用する場合は、検索結果の DBTbleModel をつぶすことになります
334         * ので、NEXT 等は使えません。DBTableModel のデータを利用した forward 等も
335         * 使用できませんので、十分ご注意ください。
336         * DEFAULT 以外の文字列の場合は、指定した文字列そのものがキーになります。
337         * 他のセッションキーと同じにすると動作が不安定になりますので、使用する場合は、
338         * "CROSS_TABLE_SAVE_KEY" を推奨致します。
339         * 指定しない場合は、セッションにセーブされません。(検索されたまま)
340         * 通常、EXCEL出力等を行う場合は、DBTableModel をセーブする必要がありますが、
341         * scope="session" にセーブすると、PREV,NEXT が使えなくなります。これは、
342         * クロス集計時に元のカラムが表形式の別のカラムに置き換えられるためです。
343         * scope="request" では、エラーは発生しなくなりますが、外部に取り出せなくなります。
344         *
345         * @og.rev 5.2.2.0 (2010/11/01) キーに、ViewCrossTableParam.SAVE_TABLEID_KEY を使用するように修正
346         *
347         * @param       id sessionに登録する時の ID
348         */
349        public void setSaveTableId( final String id ) {
350                String tableId = nval( getRequestParameter( id ),null );
351                if( "DEFAULT".equals( tableId ) ) {
352                        tableId = HybsSystem.TBL_MDL_KEY;
353                }
354                putParam( ViewCrossTableParam.SAVE_TABLEID_KEY , tableId );
355        }
356
357        /**
358         * 【TAG】クロス集計結果の DBTableModel をセーブする scope を指定します。
359         *
360         * @og.tag
361         * スコープは (request,page,session,applicaton) がありますが、request か session が
362         * 通常選択されます。
363         * また、この設定が有効になるには、saveTableId を指定する必要があります。
364         * saveTableId を指定しないと、そもそも書き出されないため、scope は無視されます。
365         *
366         * scope="session" にセーブすると、PREV,NEXT が使えなくなります。これは、
367         * クロス集計時に元のカラムが表形式の別のカラムに置き換えられるためです。
368         * scope="request" では、エラーは発生しなくなりますが、外部に取り出せなくなります。
369         * 何も指定しない場合は、viewタグに指定されたオリジナルのスコープに書き出されます。
370         * そうで無い場合は、指定のスコープに書き出されます。
371         *
372         * @og.rev 5.2.2.0 (2010/11/01) 新規追加
373         *
374         * @param       scope scopeに登録する時の キー
375         * @see         #setSaveTableId( String )
376         */
377        public void setSaveScope( final String scope ) {
378                putParam( ViewCrossTableParam.SAVE_SCOPE_KEY,
379                                  nval( getRequestParameter( scope ), null ) );
380        }
381        
382        /**
383         * 【TAG】ヘッダーカラムにラベルリソースを利用するかを指定します(初期値:false)。
384         *
385         * @og.tag
386         * HTMLCrossTableViewで、ヘッダーカラムの表示にラベルリソースを利用するかどうかを指定します。
387         * trueが指定された場合は、ヘッダー部の値のラベルで表示します。
388         * 初期値(指定無し)は、利用しない(false)です。
389         *
390         * @og.rev 5.5.5.0 (2012/07/28) 新規追加
391         *
392         * @param       useHeaderResource       ヘッダーのラベルにリソースを利用するかどうか
393         */
394        public void setUseHeaderResource( final String useHeaderResource ) {
395                putParam( ViewCrossTableParam.USE_HEADER_RSC,
396                                  nval( getRequestParameter( useHeaderResource ),"false" ) );
397        }
398        
399        /**
400         * 【TAG】ヘッダーのラベルに利用するコードリソースを指定します。
401         *
402         * @og.tag
403         * この値を指定すると上部ヘッダーの表示を対象カラムのコードに対応するラベルで表示します。
404         * カラムリソースがMENUや、DBMENUのようにSelectionを返す形である必要があります。
405         * 初期値はnullです。
406         *
407         * @og.rev 5.5.5.0 (2012/07/28) 新規追加
408         *
409         * @param       headerCode コードリソースのキー
410         */
411        public void setHeaderCodeColumn( final String headerCode ) {
412                putParam( ViewCrossTableParam.HEADER_CODE_KEY,
413                                  nval( getRequestParameter( headerCode ),null ) );
414        }
415
416        /**
417         * タグの名称を、返します。
418         * 自分自身のクラス名より、自動的に取り出せないため、このメソッドをオーバーライドします。
419         *
420         * @og.rev 4.0.0.0 (2005/01/31) 新規追加
421         *
422         * @return  タグの名称
423         */
424        @Override
425        protected String getTagName() {
426                return "crossParam" ;
427        }
428
429        /**
430         * シリアライズ用のカスタムシリアライズ書き込みメソッド
431         *
432         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
433         * @serialData 一部のオブジェクトは、シリアライズされません。
434         *
435         * @param       strm    ObjectOutputStreamオブジェクト
436         * @throws IOException  入出力エラーが発生した場合
437         */
438        private void writeObject( final ObjectOutputStream strm ) throws IOException {
439                strm.defaultWriteObject();
440        }
441
442        /**
443         * シリアライズ用のカスタムシリアライズ読み込みメソッド
444         *
445         * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
446         *
447         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
448         * @serialData 一部のオブジェクトは、シリアライズされません。
449         *
450         * @param       strm    ObjectInputStreamオブジェクト
451         * @see #release2()
452         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
453         * @throws ClassNotFoundException       クラスを見つけることができなかった場合
454         */
455        private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
456                strm.defaultReadObject();
457        }
458}