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.plugin.view;
017    
018    import java.io.Serializable;
019    import java.util.Arrays;
020    import java.util.Comparator;
021    import java.util.LinkedHashSet;
022    import java.util.Set;
023    import java.util.TreeSet;
024    
025    import org.opengion.fukurou.util.StringUtil;
026    import org.opengion.hayabusa.common.HybsSystem;
027    import org.opengion.hayabusa.common.HybsSystemException;
028    import org.opengion.hayabusa.db.DBColumn;
029    import org.opengion.hayabusa.db.DBColumnConfig;
030    import org.opengion.hayabusa.db.DBTableModel;
031    import org.opengion.hayabusa.db.DBTableModelSorter;
032    import org.opengion.hayabusa.db.DBTableModelUtil;
033    import org.opengion.hayabusa.db.Selection;
034    import org.opengion.hayabusa.html.CrossMap;
035    import org.opengion.hayabusa.html.ViewCrossTableParam;
036    import org.opengion.hayabusa.resource.CodeData;
037    import org.opengion.hayabusa.resource.ResourceManager;
038    
039    /**
040     * クロスé›?¨ˆテーブル作æ?クラスですã?
041     *
042     *   select dept.dname,emp.deptno,substrb(job,1,2) as X,job,mgr,sum(sal),count(*)
043     *   from emp,dept
044     *   where emp.deptno = dept.deptno
045     *   group by dept.dname,emp.deptno,cube(job,mgr)
046     *   order by emp.deptno,job,mgr;
047     *
048     *   HEAD1   ?šã?ãƒ?ƒ€ー。前段と同じãƒ??タは表示させなã�??
049     *   HEAD2   ?šキーブレイクさせるカラãƒ??またã?前段と同じãƒ??タは表示させなã�??
050     *   HEAD3   ?šキーブレイクさせなã�?‚«ラãƒ??またã?前段と同じãƒ??タでも表示させるã?
051     *   ROW     ?š行データのヘッãƒ??になるカラãƒ?
052     *   COL     ?šå?ãƒ??タのヘッãƒ??になるカラãƒ??下記ã?SUM1,SUM2の両方のヘッãƒ??になるã?
053     *   SUM1    ?šå?ãƒ??タの値になるカラãƒ??
054     *   SUM2    ?šå?ãƒ??タの値になるカラãƒ??
055     *
056     *   SUMカラãƒ??数、キーブレイクのカラãƒ?��、グループ化するカラãƒ?��ã‚?
057     *   æŒ?®šすることで、これらのクロスé›?¨ˆ結果の表示方法をæŒ?®šしますã?
058     *
059     *   breakColumn    = "DEPTNO"             キーブレイクのカラãƒ?��
060     *   noGroupColumns = "X"                  グループ化するカラãƒ?��
061     *   sumNumber      = "2"                  SUMカラãƒ??数
062     *   cubeXColumn    = "JOB"                CUBE計算ã??‘つ目(X)カラãƒ?‚’æŒ?®?
063     *   cubeYColumn    = "MGR"                CUBE計算ã??’つ目(Y)カラãƒ?‚’æŒ?®?
064     *   cubeSortType   = "NUMBER"             CUBE Y の列ã?ãƒ?ƒ€ーのソート方法をæŒ?®?
065     *   gokeiSortDir   = "false"              合計カラãƒ??ソート方向をæŒ?®?初期値:ソートしなã�?
066     *   shokeiLabel    = "SHOKEI"             列小計ã?カラãƒ?�«表示するラベルID
067     *   gokeiLabel     = "GOKEI"              列合計ã?カラãƒ?�«表示するラベルID
068     *   useHeaderColumn= "false"              ヘッãƒ??カラãƒ?�«レンãƒ?ƒ©ー、エãƒ?‚£ターを適用するかをæŒ?®?
069     *   useClassAdd    = "false"              å�??æƒ??のclass属æ?に、カラãƒ?��などを付与するかどã�?�‹を指å®?
070     *   useHeaderResource = "false"           ヘッãƒ??表示にラベルリソースを利用するã�?
071     *
072     *   å�?‚«ラãƒ??属æ?(HEAD,SUMç­?を認識する方æ³?
073     *
074     *     HEAD1 HEAD2 HEAD3 ROW COL SUM1 SUM2 とã�?�†並びを認識する方法ã?ã€?
075     *     多数の前提条件を利用して、å?来るだけ少なã�?ƒ‘ラメータで自動認è­?
076     *     させてã�?�¾すã?
077     *     若干ç�?§£しにくいかもしれませんがã?慣れてくださいã€?
078     *
079     *     前提条件??
080     *       ROW,COL は、å¿?�š?‘å?ずつ存在するã€?
081     *       HEAD群、ROW,COL,SUM群 とã�?�†並びになってã�?‚‹ã€?
082     *       SUM群の数は、パラメータでæŒ?®šするã?
083     *     計算方法ï¼?
084     *       HEAD数=カラãƒ?•°(7)-SUM数(2)-1(ROW,COLåˆ? ????å€?(0 ??3)
085     *       ROWアドレス?�cubeXColumn 設å®?                      (3)      ※ アドレスは?�から始まる為
086     *       COLアドレス?�cubeYColumn 設å®?                      (4)
087     *       SUMアドレス?�HEAD数?‹ï¼???カラãƒ?•°(7)-1            (5 ??6)
088     *
089     * @og.rev 3.5.4.0 (2003/11/25) 新規作æ?
090     * @og.group 画面表示
091     *
092     * @version  4.0
093     * @author       Kazuhiko Hasegawa
094     * @since    JDK5.0,
095     */
096    public class ViewForm_HTMLCrossTable extends ViewForm_HTMLTable {
097            //* こã?プログラãƒ??VERSIONæ–?­—å?を設定しますã?       {@value} */
098            private static final String VERSION = "5.5.5.0 (2012/07/28)" ;
099    
100            private String[] groupByData = null;
101            private String[] groupByCls  = null;
102    
103            // 3.5.4.8 (2004/02/23) 機è?改å–?
104            private int             rowClmNo        = -1;                   // ROWカラãƒ??カラãƒ?•ª号
105            private int             colClmNo        = -1;                   // CLMカラãƒ??カラãƒ?•ª号
106            private int             headCount       = 0;                    // HEADカラãƒ??数
107            private int             sumCount        = 1;                    // 合計カラãƒ??数
108            private int             breakClmNo      = -1;                   // ブレークするカラãƒ??カラãƒ?•ª号
109            private boolean[]       noGroupClm = null;              // グループ化する/しなã�??フラグ配å?
110            private String          shokeiLabel  = "小è¨?;   // 列小計ã?カラãƒ?�«表示するラベルID
111            private String          gokeiLabel   = "合è¨?;   // 列合計ã?カラãƒ?�«表示するラベルID
112            private String          gokeiSortDir = null;    // 列合計ã?カラãƒ?‚’ソートする方å�?
113    
114            // 3.5.6.3 (2004/07/12) ソート方式[STRING,NUMBER,LOAD]
115            private String          cubeSortType = "LOAD";
116    
117            private DBTableModel table2             = null;
118            private boolean          firstStep      = true;
119    
120            private String[]        clmKeys         = null;                         // é›?¨ˆ部のカラãƒ?‚­ー(é›?¨ˆカラãƒ?�Œè¤?•°でもä¸?�¤)の配å?
121            private String[]        clsAdd          = null;                         // 5.2.2.0 (2010/11/01) class属æ?に付与されるカラãƒ?‚­ー
122    
123            private String          noDisplayKeys           = null;         // 3.7.0.4 (2005/03/18)
124            private String          columnDisplayKeys       = null;         // 5.2.2.0 (2010/11/01)
125    
126            private boolean         firstClmGokei           = false;        // 5.0.0.3 (2009/09/22)
127            private boolean         useHeaderColumn         = false;        // 5.2.2.0 (2010/11/01)
128            private boolean         useClassAdd                     = false;        // 5.2.2.0 (2010/11/01) class属æ?にカラãƒ?‚­ーを追åŠ?�™るかどã�?�‹
129            private boolean         useHeaderResource       = false;        // 5.5.5.0 (2012/07/28)
130            private String          headerCode                      = null;         // 5.5.5.0 (2012/07/28)
131            
132            /**
133             * 初期化しますã?
134             * ここでは、å?部で使用されてã�?‚‹キャãƒ?‚·ュをクリアしã?
135             * 新しいモãƒ?ƒ«(DBTableModel)とè¨?ª?lang) をå?にå†?ƒ¨ãƒ??タをå?構築しますã?
136             * ただしã?設定情報は、以前ã?状態がそã?ままキープされてã�?�¾すã?
137             *
138             * @og.rev 3.5.4.8 (2004/02/23) paramInit メソãƒ?ƒ‰で、å?期化を行いますã?
139             * @og.rev 3.5.6.1 (2004/06/25) lang è¨?ªžコーãƒ?属æ?を削除しますã?
140             *
141             * @param       table   DBTableModelオブジェクãƒ?
142             */
143            @Override
144            public void init( final DBTableModel table ) {
145                    table2          = table;
146                    firstStep       = true;
147            }
148    
149            /**
150             * å†?®¹をクリア(初期åŒ?しますã?
151             *
152             * @og.rev 3.5.6.3 (2004/07/12) cubeSortType , gokeiSortDir 属æ?を追åŠ?�—ますã?
153             * @og.rev 3.7.0.4 (2005/03/18) noDisplayKeys 属æ?を追åŠ?�—ますã?
154             * @og.rev 3.7.1.1 (2005/05/31) shokeiLabel,gokeiLabel の初期値変更
155             * @og.rev 5.2.2.0 (2010/11/01) columnDisplayKeys、clsAdd、useClassAdd 属æ?を追åŠ?�—まã�?
156             * @og.rev 5.5.5.0 (2012/07/20) useHeaderResource追åŠ?
157             */
158            @Override
159            public void clear() {
160                    super.clear();
161                    groupByData = null;
162                    groupByCls  = null;
163                    rowClmNo        = -1;                   // ROWカラãƒ??カラãƒ?•ª号
164                    colClmNo        = -1;                   // CLMカラãƒ??カラãƒ?•ª号
165                    headCount       = 0;                    // HEADカラãƒ??数
166                    sumCount        = 1;                    // 合計カラãƒ??数
167                    breakClmNo      = -1;                   // ブレークするカラãƒ??カラãƒ?•ª号
168                    noGroupClm      = null;                 // グループ化する/しなã�??フラグ配å?
169                    table2          = null;
170                    firstStep       = true;
171                    clmKeys         = null;
172                    clsAdd          = null;                 // 5.2.2.0 (2010/11/01)
173                    shokeiLabel     = "小è¨?;                // 列小計ã?カラãƒ?�«表示するラベルID
174                    gokeiLabel      = "合è¨?;                // 列合計ã?カラãƒ?�«表示するラベルID
175                    cubeSortType = "LOAD";          // 3.5.6.3 (2004/07/12)
176                    gokeiSortDir = null;            // 3.5.6.3 (2004/07/12) 列合計ã?カラãƒ?‚’ソートする方å�?
177                    noDisplayKeys           = null; // 3.7.0.4 (2005/03/18)
178                    columnDisplayKeys       = null; // 5.2.2.0 (2010/11/01)
179                    firstClmGokei           = false;        // 5.2.2.0 (2010/11/01)
180                    useHeaderColumn         = false;        // 5.2.2.0 (2010/11/01)
181                    useClassAdd                     = false;        // 5.2.2.0 (2010/11/01)
182                    useHeaderResource       = false;        // 5.5.5.0 (2012/07/20)
183                    headerCode                      = null;         // 5.5.5.0 (2012/07/28)
184            }
185    
186            /**
187             * DBTableModel から HTMLæ–?­—å?を作æ?して返しますã?
188             * startNo(表示開始位置)から、pageSize(表示件数)までのViewæ–?­—å?を作æ?しますã?
189             * 表示残りãƒ??タã�?pageSize 以下ã?場合ã?,残りのãƒ??タをすべて出力しますã?
190             *
191             * @og.rev 3.5.5.0 (2004/03/12) No æ¬?��のもã?の作æ?判断ロジãƒ?‚¯を追åŠ?
192             * @og.rev 3.5.6.1 (2004/06/25) lang è¨?ªžコーãƒ?属æ?を削除しますã?
193             * @og.rev 3.5.6.4 (2004/07/16) ヘッãƒ??とボディー部をJavaScriptでåˆ?›¢
194             * @og.rev 3.7.0.4 (2005/03/18) setNoDisplay メソãƒ?ƒ‰を追åŠ?
195             * @og.rev 4.3.1.0 (2008/09/08) 編é›?¡Œã?みを表示する属æ?(isSkipNoEdit)追åŠ?
196             * @og.rev 5.0.0.3 (2009/09/22) 合計å?をcubeの先é?に出せるようにする
197             * @og.rev 5.1.0.0 (2009/11/04) ↑で合計å?がè¤?•°カラãƒ?­˜在する場合に正しく表示されなã�?ƒ�グを修正
198             * @og.rev 5.2.2.0 (2010/11/01) setColumnDisplay メソãƒ?ƒ‰を追åŠ?
199             *
200             * @param  startNo        表示開始位置
201             * @param  pageSize   表示件数
202             *
203             * @return      DBTableModelから作æ?されã�?HTMLæ–?­—å?
204             */
205            @Override
206            public String create( final int startNo, final int pageSize )  {
207                    if( firstStep ) {
208                            paramInit( table2 );
209                            super.init( makeCrossTable(table2) );
210                            super.setNoDisplay( noDisplayKeys ) ;                           // 3.7.0.4 (2005/03/18)
211                            super.setColumnDisplay( columnDisplayKeys ) ;           // 5.2.2.0 (2010/11/01)
212                            markerSet( this );              // 3.5.6.4 (2004/07/16)
213                            firstStep = false;
214                    }
215    
216                    if( getRowCount() == 0 ) { return ""; } // 暫定å?置
217    
218                    int clmCnt = getColumnCount();  // 3.5.5.7 (2004/05/10)
219    
220                    headerLine       = null;
221    
222                    int lastNo = getLastNo( startNo, pageSize );
223                    int blc = getBackLinkCount();
224                    String backData = null;
225    
226                    StringBuilder out = new StringBuilder( HybsSystem.BUFFER_LARGE );
227    
228                    out.append( getCountForm( startNo,pageSize ) );
229                    out.append( getHeader() );
230    
231                    String ckboxTD = "  <td class=\"" + ViewCrossTableParam.HEADER1 + "\">";
232    
233                    out.append("<tbody>").append( HybsSystem.CR );
234                    int bgClrCnt = 0;
235                    boolean shokei;
236                    for( int row=startNo; row<lastNo; row++ ) {
237    //                      if( isSkip( row ) ) { continue; }               // 3.5.3.1 (2003/10/31)
238                            if( isSkip( row ) || isSkipNoEdit( row ) ) { continue; } // 4.3.1.0 (2008/09/08)
239                            // キーブレイク時ã?ヘッãƒ??設å®?
240                            if( breakClmNo >= 0 ) {
241                                    String val = getValue( row,breakClmNo );
242                                    if( backData == null ) {        // キーブレイクの初期ãƒ??タ設定ã?
243                                            backData = val;
244                                    }
245                                    else {
246                                            if( ! backData.equals( val ) ) {
247                                                    backData = val;
248                                                    out.append( getHeadLine() );
249                                            }
250                                    }
251                            }
252                            // 小計ã?ãƒ?ƒ€ー時ã?クラス設å®?
253                            String val2 = getValue( row,rowClmNo );
254                            if( val2.length() == 0 ) {
255                                    shokei = true;
256                                    out.append("<tr class=\"").append( ViewCrossTableParam.SHOKEI ).append("\">");
257                            }
258                            else {
259                                    shokei = false;
260                                    out.append("<tr").append( getBgColorCycleClass( bgClrCnt++ ) ).append(">");
261                            }
262                            out.append( HybsSystem.CR );
263                            // 3.5.5.0 (2004/03/12) No æ¬?��のもã?の作æ?判断追åŠ?
264                            if( isNumberDisplay() ) {
265                                    out.append( makeCheckbox( ckboxTD, row, blc ) ).append( HybsSystem.CR );
266                            }
267                            for(int column = 0; column < clmCnt; column++) {
268                                    if( isColumnDisplay( column ) ) {
269                                            if( column < headCount-1 ) {         // CUBEではなã�?¡Œã?ãƒ?ƒ€ー部
270                                                    String val = getGroupData( column,getRendererValue(row,column) );
271                                                    out.append("  <td class=\"").append( groupByCls[column] ).append("\">");
272                                                    out.append( val );
273                                            }
274                                            else if( column == headCount-1 ) {      // ヘッãƒ??のæœ?¾Œ尾
275                                                    if( shokei ) {
276                                                            out.append("  <td class=\"").append( ViewCrossTableParam.SHOKEI ).append("\">");
277                                                            out.append( shokeiLabel );
278                                                    }
279                                                    else {
280                                                            if( breakClmNo > 0 ) {       // ヘッãƒ??があるå?å�?
281                                                                    out.append("  <td class=\"").append( groupByCls[column-1] ).append("\">");
282                                                            }
283                                                            else {
284                                                                    out.append("  <td class=\"").append( ViewCrossTableParam.HEADER1 ).append("\">");
285                                                            }
286                                                            out.append( getRendererValue(row,column) );
287                                                    }
288                                            }
289                                            // else if( column >= clmCnt-sumCount ) {    // CUBEのæœ?µ‚カラãƒ?列合è¨?
290                                            else if( column >= clmCnt-sumCount && ! firstClmGokei ) {    // 5.0.0.3 (2009/09/22) CUBEのæœ?µ‚カラãƒ?列合è¨?
291                                                    out.append("  <td class=\"").append( ViewCrossTableParam.SHOKEI ).append("\">");
292                                                    out.append( getRendererValue(row,column) );
293                                            }
294    //                                      else if( column == headCount && firstClmGokei ) {               // 5.0.0.3 (2009/09/22) CUBEの先é?カラãƒ?列合è¨?
295                                            else if( column >= headCount && column < headCount + sumCount && firstClmGokei ) {                // 5.1.0.0 (2009/11/04)
296                                                            out.append("  <td class=\"").append( ViewCrossTableParam.SHOKEI ).append("\">");
297    //                                                      out.append( getRendererValue(row,clmCnt-sumCount) );
298                                                            out.append( getRendererValue(row,clmCnt-sumCount+(column-headCount)) ); // 5.1.0.0 (2009/11/04)
299                                            }
300                                            else {          // カラãƒ?SUMåˆ?
301                                                    if( useClassAdd && clsAdd[column] != null ) {
302                                                            out.append("  <td class=\"").append( clsAdd[column] ).append("\">");
303                                                    }
304                                                    else {
305                                                            out.append("  <td>");
306                                                    }
307                                                    if( firstClmGokei ){
308    //                                                      out.append( getRendererValue(row,column-1) ); // 合計行を先é?に出すと1つずれã‚?
309                                                            out.append( getRendererValue(row,column-sumCount) ); // 5.1.0.0 (2009/11/04)
310                                                    }
311                                                    else{
312                                                            out.append( getRendererValue(row,column) );
313                                                    }
314                                            }
315                                            out.append("</td>").append( HybsSystem.CR );
316                                    }
317                            }
318                            out.append("</tr>").append( HybsSystem.CR );
319                    }
320                    out.append("</tbody>").append( HybsSystem.CR );
321                    out.append("</table>").append( HybsSystem.CR );
322    
323                    out.append( getScrollBarEndDiv() );     // 3.8.0.3 (2005/07/15)
324                    return out.toString();
325            }
326    
327            /**
328             * パラメータå†?®¹をå?期化しますã?
329             *
330             * @og.rev 3.5.4.8 (2004/02/23) 新規作æ?
331             * @og.rev 3.5.6.3 (2004/07/12) 列ã?ãƒ?ƒ€ーのソート方法をæŒ?®?
332             * @og.rev 5.0.0.3 (2009/09/22) 合計行をCUBEの先é?に持ってくるためのフラグ追åŠ?
333             * @og.rev 5.2.2.0 (2010/11/01) useHeaderColumn,useClassAdd 属æ?の追åŠ?
334             *
335             * @param       table   入力もとの DBTableModelオブジェクãƒ?
336             */
337            private void paramInit( final DBTableModel table ) {
338                    String breakColumn              = getParam( ViewCrossTableParam.BREAK_COLUMN_KEY     , null );
339                    String noGroupColumns   = getParam( ViewCrossTableParam.NO_GROUP_COLUMNS_KEY , null );
340                    String sumNumber                = getParam( ViewCrossTableParam.SUM_NUMBER_KEY       , null );
341                    shokeiLabel                             = getParam( ViewCrossTableParam.SHOKEI_LABEL_KEY     , shokeiLabel );
342                    gokeiLabel                              = getParam( ViewCrossTableParam.GOKEI_LABEL_KEY      , gokeiLabel );
343                    String cubeXColumn              = getParam( ViewCrossTableParam.CUBE_X_COLUMN_KEY    , null );  // CUBE計算ã??‘つ目(X)カラãƒ?‚’æŒ?®?
344                    String cubeYColumn              = getParam( ViewCrossTableParam.CUBE_Y_COLUMN_KEY    , null );  // CUBE計算ã??’つ目(Y)カラãƒ?‚’æŒ?®?
345                    cubeSortType                    = getParam( ViewCrossTableParam.CUBE_SORT_TYPE_KEY   , "LOAD" );        // 3.5.6.3 (2004/07/12)
346                    gokeiSortDir                    = getParam( ViewCrossTableParam.GOKEI_SORT_DIR_KEY   , null );  // 3.5.6.3 (2004/07/12)
347                    firstClmGokei                   = StringUtil.nval( getParam( ViewCrossTableParam.FIRST_CLM_GOKEI_KEY , null ), false);  // 5.0.0.3 (2009/09/22)
348                    useHeaderColumn                 = StringUtil.nval( getParam( ViewCrossTableParam.USE_HEADER_COLUMN   , null ), false);  // 5.2.2.0 (2010/11/01)
349                    useClassAdd                             = StringUtil.nval( getParam( ViewCrossTableParam.USE_CLASS_ADD       , null ), false);  // 5.2.2.0 (2010/11/01)
350                    useHeaderResource               = StringUtil.nval( getParam( ViewCrossTableParam.USE_HEADER_RSC      , null ), false);  // 5.5.5.0 (2012/07/20)
351                    headerCode                              = getParam( ViewCrossTableParam.HEADER_CODE_KEY     , null );   // 5.5.5.0 (2012/07/28)
352                    
353                    if( sumNumber != null ) {
354                            sumCount = Integer.parseInt( sumNumber );
355                    }
356    
357                    // HEAD数=カラãƒ?•°-SUM数-1(COLåˆ? ROW は、HEADに含みますã?
358                    headCount = table.getColumnCount() - sumCount - 1;
359    
360                    // 3.5.5.9 (2004/06/07)
361                    if( cubeXColumn != null ) {
362                            rowClmNo = table.getColumnNo( cubeXColumn );
363                    }
364                    else {
365                            rowClmNo = headCount-1;                 // ROWカラãƒ??カラãƒ?•ª号
366                    }
367    
368                    // 3.5.5.9 (2004/06/07)
369                    if( cubeYColumn != null ) {
370                            colClmNo = table.getColumnNo( cubeYColumn );
371                    }
372                    else {
373                            colClmNo = headCount;           // CLMカラãƒ??カラãƒ?•ª号
374                    }
375    
376                    if( breakColumn != null ) {
377                            breakClmNo = table.getColumnNo( breakColumn );
378                    }
379    
380                    groupByData = new String[headCount];
381                    groupByCls  = new String[headCount];
382                    Arrays.fill( groupByCls,ViewCrossTableParam.HEADER2 );          // 変であるがã?æœ??に入れ替えが発生する為ã€?
383    
384                    noGroupClm    = new boolean[headCount];         // グループ化する/しなã�??フラグ配å?
385                    Arrays.fill( noGroupClm,false );
386    
387                    if( noGroupColumns != null ) {
388                            String[] gClms = StringUtil.csv2Array( noGroupColumns );
389                            for( int i=0; i<gClms.length; i++ ) {
390                                    noGroupClm[table.getColumnNo( gClms[i] )] = true;
391                            }
392                    }
393    
394                    if( ! "true".equalsIgnoreCase( gokeiSortDir ) &&
395                            ! "false".equalsIgnoreCase( gokeiSortDir ) ) {
396                                    gokeiSortDir = null;
397                    }
398            }
399    
400            /**
401             * CUBEではなã�?¡Œã?ãƒ?ƒ€ー部の値が前と同じならã?、ゼロæ–?­—å?を返しますã?
402             *
403             * @param       clm     カラãƒ?•ª号
404             * @param       val     比è¼?�™るå?
405             *
406             * @return      前と同じなã‚?""をã?異なるå?合ã?、引数の val を返しますã?
407             */
408            private String getGroupData( final int clm,final String val ) {
409                    if( noGroupClm[clm] ) { return val; }
410    
411                    if( val.equals( groupByData[clm] )) {
412                            return "";
413                    }
414                    else {
415                            groupByData[clm] = val;
416                            groupByCls[clm] = ( groupByCls[clm].equals( ViewCrossTableParam.HEADER1 )) ? ViewCrossTableParam.HEADER2 : ViewCrossTableParam.HEADER1 ;
417                            return val;
418                    }
419            }
420    
421            /**
422             * 選択用のチェãƒ?‚¯ボックスと行番号と変更タイãƒ?A,C,D)を表示しますã?
423             *
424             * @param  ckboxTD チェãƒ?‚¯ボックスのタグ(マルチカラãƒ?™‚のrowspan対å¿?
425             * @param  row   行番号
426             * @param  blc   バックラインカウンãƒ?先é?へ戻るリンク間隔)
427             *
428             * @return      tdタグで囲まれたチェãƒ?‚¯ボックスのHTMLæ–?­—å?
429             */
430            @Override
431            protected String makeCheckbox( final String ckboxTD,final int row,final int blc ) {
432                    StringBuilder out = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
433    
434                    out.append( ckboxTD ).append("</td>");
435                    out.append( ckboxTD ).append("</td>");
436                    out.append( ckboxTD );
437                    // 3.5.1.0 (2003/10/03) Noカラãƒ?�«、numberType 属æ?を追åŠ?
438                    if( blc != 0 && (row+1) % blc == 0 ) {
439                            out.append( "<a href=\"#top\">" ).append( (row+1) ).append(  "</a>" );
440                    } else {
441                            out.append( (row+1) );
442                    }
443                    out.append("</td>");
444    
445                    return out.toString();
446            }
447    
448            /**
449             * ヘッãƒ??繰り返し部をã?getTableHead()メソãƒ?ƒ‰からåˆ?›¢ã€?
450             *
451             * @og.rev 3.5.4.5 (2004/01/23) 実è£?‚’getHeadLine( String thTag )に移å‹?
452             * @og.rev 3.5.5.0 (2004/03/12) No æ¬?��のもã?の作æ?判断ロジãƒ?‚¯を追åŠ?
453             * @og.rev 5.0.0.3 (2009/09/17) 合計行を出力する位置をfirstClmGokeiで変えã‚?
454             * @og.rev 5.2.2.0 (2010/11/01) é›?¨ˆ部の ColumnDisplay/NoDisplay 対å¿?
455             * @og.rev 5.5.5.0 (2012/07/28) useHeaderResource利用時ã?ヘッãƒ??ラベル/コードリソース対å¿?
456             *
457             * @return      ãƒ??ブルのタグæ–?­—å?
458             */
459            @Override
460            protected String getHeadLine() {
461                    if( headerLine != null ) { return headerLine; }         // キャãƒ?‚·ュを返すã€?
462    
463                    String rowspan = "";
464                    if( sumCount > 1 ) { rowspan = " rowspan=\"2\""; }
465    
466                    String thTag = "<th" + rowspan;
467    
468                    StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
469    
470                    buf.append("<tr").append( rowspan ).append(" class=\"row_h\"").append(" >").append( HybsSystem.CR );
471    
472                    // 3.5.5.0 (2004/03/12) No æ¬?��のもã?の作æ?判断追åŠ?
473                    if( isNumberDisplay() ) {
474                            buf.append( thTag ).append(" colspan='3'>").append( getNumberHeader() ).append("</th>");
475                    }
476    
477                    buf.append( HybsSystem.CR );
478                    // ヘッãƒ??部åˆ??、そのまま表示しますã?
479                    for(int column = 0; column < headCount; column++) {
480                            if( isColumnDisplay( column ) ) {
481                                    buf.append( thTag ).append(">");
482                                    buf.append( getColumnLabel(column) );
483                                    buf.append("</th>").append( HybsSystem.CR );
484                            }
485                    }
486    
487                    // ヘッãƒ??部åˆ?上段)は、カラãƒ??列を利用しますã?
488                    String colspan = "";
489                    if( sumCount > 1 ) { colspan = " colspan='" + sumCount + "'"; }
490    
491                    // 5.2.2.0 (2010/11/01) é›?¨ˆ部の ColumnDisplay/NoDisplay 対å¿?
492    //              String gokeiClm = "<th" + colspan + ">" + temp + "</th>" + HybsSystem.CR ;
493                    String gokeiClm = null;
494                    if( isColumnDisplay( headCount+(clmKeys.length-1)*sumCount ) ) {
495                            String temp = clmKeys[clmKeys.length-1];
496                            if( temp == null || temp.length() == 0 ) {
497                                    temp = gokeiLabel;
498                            }
499    
500                            gokeiClm = "<th" + colspan + ">" + temp + "</th>" + HybsSystem.CR ;
501                    }
502    
503                    // 5.2.2.0 (2010/11/01) æœ?¾Œã?カラãƒ?�Œ、合計行ã?
504                    // 5.0.0.3 (2009/09/22) firstClmGokei ã�?trueの場合ã?cubeの先é?に出すよã�?�«しますã?
505    //              if( firstClmGokei && isColumnDisplay( headCount+clmKeys.length-1 ) ) {
506                    if( firstClmGokei && gokeiClm != null ) {
507                            buf.append( gokeiClm );
508                    }
509    
510    //              // 5.0.0.3 (2009/09/22) trueの場合ã?cubeの先é?に出すよã�?�«しますã?
511    //              if( firstClmGokei ){
512    //                      String temp = clmKeys[clmKeys.length-1];
513    //                      if( temp == null || temp.length() == 0 ) {
514    //                              temp = gokeiLabel;
515    //                      }
516    //                      buf.append( "<th").append( colspan ).append( ">" );
517    //                      buf.append( temp );
518    //                      buf.append("</th>").append( HybsSystem.CR );
519    //              }
520    
521                    // 3.7.0.4 (2005/03/18) カラãƒ??列ã?、カラãƒ?•ª号と別物
522                    ResourceManager resource = getResourceManager();
523                    Selection selection = null;
524                    if( headerCode != null && headerCode.length() > 0 && resource != null ){
525                            DBColumn clmTmp = resource.getDBColumn( headerCode );
526                            //selection = new Selection_CODE(resource.getCodeData( headerCode )); code直の場å�?
527                            if ( clmTmp != null ){
528                                    selection = clmTmp.getSelection();
529                            }
530                    }
531                    for( int keyNo = 0; keyNo < clmKeys.length-1; keyNo++ ) {
532                            // 5.2.2.0 (2010/11/01) ColumnDisplay/NoDisplay 対å¿?
533                            if( isColumnDisplay( headCount+keyNo ) ) {
534                                    buf.append( "<th").append( colspan ).append( ">" );
535                                    if( headerCode != null && headerCode.length() > 0 && selection != null ){
536                                            buf.append( selection.getValueLabel( clmKeys[keyNo] ) );
537                                    }
538                                    else if( useHeaderResource && useHeaderColumn ){ // 5.5.5.0 (2012/07/28) ヘッãƒ??リソース対å¿?
539                                            buf.append( getColumnLabel(headCount+keyNo) );
540                                    }
541                                    else{
542                                            buf.append( clmKeys[keyNo] );
543                                    }
544                                    buf.append("</th>").append( HybsSystem.CR );
545                            }
546                    }
547    
548                    // 5.2.2.0 (2010/11/01) æœ?¾Œã?カラãƒ?�Œ、合計行ã?
549                    // 5.0.0.3 (2009/09/22) firstClmGokei ã�?trueの場合ã?cubeの先é?に出すよã�?�«しますã?
550    //              if( ! firstClmGokei && isColumnDisplay( headCount+clmKeys.length-1 ) ) {
551                    if( ! firstClmGokei && gokeiClm != null ) {
552                            buf.append( gokeiClm );
553                    }
554    
555                    // 3.5.6.2 (2004/07/05) makeCrossTable( DBTableModel table ) に移å‹?
556                    // æœ?µ‚カラãƒ?åˆ?がNULL(空æ–?­—å?)の場合ã?列合計ですã?
557    //              if( ! firstClmGokei ){ // 5.0.0.3 (2009/09/22) falseの場合ã?æœ?µ‚å?に出ã�?
558    //                      String temp = clmKeys[clmKeys.length-1];
559    //                      if( temp == null || temp.length() == 0 ) {
560    //                              temp = gokeiLabel;
561    //                      }
562    //                      buf.append( "<th").append( colspan ).append( ">" );
563    //                      buf.append( temp );
564    //                      buf.append("</th>").append( HybsSystem.CR );
565    //              }
566    
567                    buf.append("</tr>").append( HybsSystem.CR );
568    
569                    if( sumCount > 1 ) {
570                            buf.append("<tr").append(" class=\"row_h\"").append(" >").append( HybsSystem.CR );
571                            int clmCnt = getColumnCount();  // 3.5.5.7 (2004/05/10)
572                            for(int column = headCount; column < clmCnt; column++) {
573                                    if( isColumnDisplay( column ) ) {
574                                            buf.append( "<th>");
575                                            buf.append( getColumnLabel(column) );
576                                            buf.append("</th>").append( HybsSystem.CR );
577                                    }
578                            }
579                            buf.append("</tr>").append( HybsSystem.CR );
580                    }
581    
582                    headerLine = buf.toString();
583                    return headerLine;
584            }
585    
586            /**
587             * クロスé›?¨ˆ結果の DBTableModelオブジェクトを作æ?しますã?
588             *
589             * @og.rev 3.5.4.8 (2004/02/23) paramInit メソãƒ?ƒ‰で、å?期化を行いますã?
590             * @og.rev 3.5.6.3 (2004/07/12) 列ã?ãƒ?ƒ€ーのソート可否のæŒ?®šを追åŠ?
591             * @og.rev 4.0.0.0 (2007/11/27) ヘッãƒ??カラãƒ??エãƒ?‚£ター、レンãƒ?ƒ©ー適用対å¿?
592             * @og.rev 4.3.5.7 (2008/03/22) ↑リソースが存在しなã�??合ã?、ラベルのみ入れ替ã�?
593             * @og.rev 5.2.2.0 (2010/11/01) useHeaderColumn,useClassAdd 属æ?の追åŠ?
594             *
595             * @param       table   入力もとの DBTableModelオブジェクãƒ?
596             *
597             * @return      DBTableModelオブジェクãƒ?
598             */
599            private DBTableModel makeCrossTable( final DBTableModel table ) {
600                    Set<String> clmData = gatSortAlgorithmSet();
601    
602                    // 列ã?キーとなるカラãƒ??値を取得しますã?
603                    int rowCnt = table.getRowCount();               // 3.5.5.7 (2004/05/10)
604                    for( int row=0; row<rowCnt; row++ ) {
605                            String clm = table.getValue( row,colClmNo );
606                            if( clm.length() > 0 ) { clmData.add( clm ); }
607                    }
608                    // ゼロストリングは、合計行になりますã?で、最後に追åŠ?�—ますã?
609    
610                    // 3.5.6.3 (2004/07/12) ゼロストリングは、合計行になりますã?で、最後に追åŠ?�—ますã?
611    //              clmKeys = new String[ clmData.size() + 1 ];
612    //              clmKeys = clmData.toArray( clmKeys ) ;
613                    clmKeys = clmData.toArray( new String[clmData.size() + 1] ) ;
614    
615                    clmKeys[clmKeys.length-1] = "" ;
616    
617                    int numberOfColumns =  headCount + clmKeys.length * sumCount ;
618    
619                    DBTableModel tableImpl = DBTableModelUtil.newDBTable();
620                    tableImpl.init( numberOfColumns );
621    
622                    // ヘッãƒ??カラãƒ?ROWãƒ??タ含ã‚?は、そのまま、設定しますã?
623                    for(int column=0; column<headCount; column++) {
624                            tableImpl.setDBColumn( column,table.getDBColumn(column) );
625                    }
626    
627                    // 列情報は、合計å?のカラãƒ?®š義を使用しますã?
628                    DBColumn[] dbColumn = new DBColumn[sumCount];
629                    for( int i=0; i<sumCount; i++ ) {
630                            dbColumn[i] = table.getDBColumn(headCount + 1 + i);
631                    }
632    
633                    // 列情報は、å?の名前をカラãƒ??値に変えて、合計カラãƒ??のコピã?æƒ??を設定しますã?
634    
635                    int sumId = 0;
636                    ResourceManager resource = getResourceManager();
637                    useHeaderColumn = useHeaderColumn && resource != null ; // 5.2.2.0 (2010/11/01)
638    
639                    // 5.2.2.0 (2010/11/01) useClassAdd 属æ?の追åŠ?
640    
641                    clsAdd = new String[numberOfColumns];
642    
643                    // 列情報カラãƒ??、ã?ãƒ?ƒ€ーåˆ?�«割り当てられる為ã€?–‹始が、headCount からになりますã?
644                    for(int column=headCount; column<numberOfColumns; column++) {
645                            DBColumn dbClm = dbColumn[sumId];
646                            String clmKey  = clmKeys[ (column-headCount)/sumCount ];
647    
648                            // 5.2.2.0 (2010/11/01) useClassAdd 属æ?の追åŠ?
649                            if( useClassAdd ) {
650                                     // ※ 特殊対応:cssなどでæŒ?®šできるIDやCLASS属æ?は、å?頭æ–?­—が数字ã?場合ã?ã€?
651                                     // 無効になりますã?(つまりã?効きませんã€?
652                                     // 表示ヘッãƒ??は、年月や、社員番号(数å­?などのケースもありますã?そこで、å?頭が数字ã?
653                                     // 場合ã?ã€?x"(小文字ã?x)をè?動的に頭に追åŠ?�—ますã?
654                                    StringBuilder buf = new StringBuilder();
655                                    if( clmKey != null && clmKey.length() > 0 ) {
656                                            char ch = clmKey.charAt(0);
657                                            if( ch >= '0' && ch <= '9' ) {
658                                                    buf.append( "x" );
659                                            }
660                                            buf.append( clmKey );
661                                    }
662    
663                                    String nm = dbClm.getName();
664                                    if( nm != null && nm.length() > 0 ) {
665                                            buf.append( " " );
666                                            char ch = nm.charAt(0);
667                                            if( ch >= '0' && ch <= '9' ) {
668                                                    buf.append( "x" );
669                                            }
670                                            buf.append( nm );
671                                    }
672                                    clsAdd[column] = buf.toString();
673                            }
674    
675                            // 4.0.0.0 (2007/11/27)
676    //                      if( resource != null && "true".equalsIgnoreCase( getParam( "useHeaderColumn", null ) ) ) {
677                            // 5.2.2.0 (2010/11/01) 処ç�?¦‹直しã?useHeaderColumn の前å?しと、setName 対å¿?
678                            if( useHeaderColumn ) {
679    //                              String clmKey = clmKeys[ (column-headCount)/sumCount ]; // 5.2.2.0 (2010/11/01) 上に移å‹?
680                                    DBColumn clmTmp = resource.getDBColumn( clmKey );
681                                    if( clmTmp == null ) {
682    //                                      tableImpl.setDBColumn( column,dbColumn[sumId] ); }
683                                            DBColumnConfig dbCfg2 = dbClm.getConfig();
684                                            if( clmKey != null && clmKey.length() > 0 ) {        // 5.2.2.0 (2010/11/01)
685                                                    dbCfg2.setName( clmKey );
686                                                    dbCfg2.setLabelData( resource.getLabelData( clmKey ) );
687                                            }
688                                            else {
689                                                    dbCfg2.setLabelData( resource.getLabelData( gokeiLabel ) );
690                                            }
691                                            dbClm = new DBColumn( dbCfg2 );
692    //                                      tableImpl.setDBColumn( column, new DBColumn( dbCfg2 ) );
693                                    }
694                                    else {
695    //                                      tableImpl.setDBColumn( column,dbClm );
696                                            dbClm = clmTmp;
697                                    }
698                            }
699    //                      else {
700    //                              tableImpl.setDBColumn( column,dbColumn[sumId] );
701    //                      }
702    
703                            tableImpl.setDBColumn( column,dbClm );
704    
705                            sumId++;
706                            if( sumId % sumCount == 0 ) {
707                                    sumId = 0;
708                            }
709                    }
710    
711                    // クロスé›?¨ˆデータの作æ?
712                    CrossMap cross = new CrossMap( clmKeys,headCount,sumCount );
713                    for( int row=0; row<rowCnt; row++ ) {
714                            String[] data = table.getValues( row );
715                            cross.add( data );
716                    }
717    
718                    // ãƒ??タ部の設å®?
719                    int size = cross.getSize();
720                    for( int row=0; row<size; row++ ) {
721                            tableImpl.addValues( cross.get( row ), row );
722                    }
723    
724                    tableImpl.resetModify();
725    
726                    final DBTableModel model ;
727                    if( gokeiSortDir != null ) {
728                            DBTableModelSorter temp = new DBTableModelSorter();
729                            temp.setModel( tableImpl );
730    
731                            boolean direction = Boolean.valueOf( gokeiSortDir ).booleanValue();
732                            temp.sortByColumn( numberOfColumns-1,direction );
733                            model = temp ;
734                    }
735                    else {
736                            model = tableImpl;
737                    }
738                    return model ;
739            }
740    
741            /**
742             * 列ã?ãƒ?ƒ€ーのソート方法に応じたã?Setオブジェクトを返しますã?
743             * ここでは、NUMBER , STRING , LOAD の?“種類用意してã�?�¾すã?
744             *
745             * @og.rev 3.5.6.3 (2004/07/12) 新規作æ?
746             *
747             * @return      ソート方法に応じたSetオブジェクãƒ?
748             */
749            private Set<String> gatSortAlgorithmSet() {
750                    final Set<String> rtnSet ;
751    
752                    if( "LOAD".equalsIgnoreCase( cubeSortType ) ) {
753                            rtnSet = new LinkedHashSet<String>();
754                    }
755                    else if( "NUMBER".equalsIgnoreCase( cubeSortType ) ) {
756                            rtnSet = new TreeSet<String>( numberSort );
757                    }
758                    else if( "STRING".equalsIgnoreCase( cubeSortType ) ) {
759                            rtnSet = new TreeSet<String>();
760                    }
761                    else {
762                            String errMsg = "cubeSortType は、NUMBER,STRING,LOAD 以外指定できませんã€? +
763                                                            "  cubeSortType=[" + cubeSortType + "]";
764                            throw new HybsSystemException( errMsg );
765                    }
766    
767                    return rtnSet ;
768            }
769    
770            /**
771             * 表示不可カラãƒ?��をã?カンマ区åˆ?‚Šで与えますã?
772             * 例ï¼?OYA,KO,HJO,SU,DYSET,DYUPD"
773             * null を与えたå?合ã?,なにもしませんã€?
774             *
775             * 注意:このクラスでは、DBTableModel を作り直すタイミングがã?
776             * create メソãƒ?ƒ‰実行時ですã?(パラメータの初期化がå¿?¦�な為)
777             * よって、このメソãƒ?ƒ‰は、å?期が終äº?¾Œに、å?セãƒ?ƒˆしますã?
778             *
779             * @og.rev 3.7.0.4 (2005/03/18) 新規作æ?
780             *
781             * @param       columnName      カラãƒ?��
782             */
783            @Override
784            public void setNoDisplay( final String columnName ) {
785                    noDisplayKeys = columnName;
786            }
787    
788            /**
789             * 表示可能カラãƒ?��をã?カンマ区åˆ?‚Šで与えますã?
790             * 例ï¼?OYA,KO,HJO,SU,DYSET,DYUPD"
791             * setColumnDisplay( int column,boolean rw ) の簡易版ですã?
792             * null を与えたå?合ã?,なにもしませんã€?
793             * またã?全カラãƒ?�«つã�?�¦、有効にする場合ã?、columnName="*" を設定しますã?
794             *
795             * @og.rev 5.2.2.0 (2010/11/01) 新規追åŠ?
796             *
797             * @param       columnName      カラãƒ?��
798             */
799            @Override
800            public void setColumnDisplay( final String columnName ) {
801                    columnDisplayKeys = columnName;
802            }
803    
804            /**
805             * NUMBER ソート機è?(整数限å®? å†?ƒ¨クラス
806             * これは通常のソートではなくã?ヘッãƒ??に使ã�?ƒ©ベルのソートなのでã€?
807             * 整数のみと限定しますã?実数の場合ã?、桁合わせ(小数点以下ã?桁数)
808             * されてã�?‚‹とã�?�†前提ですã?
809             *
810             * @og.rev 3.5.6.3 (2004/07/12) 新規作æ?
811             *
812             */
813            private static final Comparator<String> numberSort = new NumberComparator();
814    
815            private static class NumberComparator implements Comparator<String>,Serializable {
816                    private static final long serialVersionUID = 4000 ;     // 4.0.0 (2005/01/31)
817    
818                    public int compare( final String s1, final String s2 ) {
819                            if( s1.length() > s2.length() )      { return 1;  }
820                            else if( s1.length() < s2.length() ) { return -1; }
821                            else {
822                                    return s1.compareTo( s2 );
823                            }
824                    }
825            }
826    
827            /**
828             * 表示é ?›®の編é›?並び替ã�?が可能かどã�?�‹を返しまã�?
829             *
830             * @og.rev 5.1.6.0 (2010/05/01) 新規追åŠ?
831             *
832             * @return      表示é ?›®の編é›?並び替ã�?が可能かどã�?�‹(false:不可能)
833             */
834            @Override
835            public boolean isEditable() {
836                    return false;
837            }
838    }