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.7.4.3 (2014/03/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             * @og.rev 5.7.4.2 (2014/03/20) ヘッãƒ??のリソース適用見直ã�?
457             * @og.rev 5.7.4.3 (2014/03/28) useHeaderResource 単独でリソース適用しますã?
458             *
459             * @return      ãƒ??ブルのタグæ–?­—å?
460             */
461            @Override
462            protected String getHeadLine() {
463                    if( headerLine != null ) { return headerLine; }         // キャãƒ?‚·ュを返すã€?
464    
465                    String rowspan = "";
466                    if( sumCount > 1 ) { rowspan = " rowspan=\"2\""; }
467    
468                    String thTag = "<th" + rowspan;
469    
470                    StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
471    
472                    buf.append("<tr").append( rowspan ).append(" class=\"row_h\"").append(" >").append( HybsSystem.CR );
473    
474                    // 3.5.5.0 (2004/03/12) No æ¬?��のもã?の作æ?判断追åŠ?
475                    if( isNumberDisplay() ) {
476                            buf.append( thTag ).append(" colspan='3'>").append( getNumberHeader() ).append("</th>");
477                    }
478    
479                    buf.append( HybsSystem.CR );
480                    // ヘッãƒ??部åˆ??、そのまま表示しますã?
481                    for(int column = 0; column < headCount; column++) {
482                            if( isColumnDisplay( column ) ) {
483                                    buf.append( thTag ).append(">");
484                                    buf.append( getColumnLabel(column) );
485                                    buf.append("</th>").append( HybsSystem.CR );
486                            }
487                    }
488    
489                    // ヘッãƒ??部åˆ?上段)は、カラãƒ??列を利用しますã?
490                    String colspan = "";
491                    if( sumCount > 1 ) { colspan = " colspan='" + sumCount + "'"; }
492    
493                    // 5.2.2.0 (2010/11/01) é›?¨ˆ部の ColumnDisplay/NoDisplay 対å¿?
494    //              String gokeiClm = "<th" + colspan + ">" + temp + "</th>" + HybsSystem.CR ;
495                    String gokeiClm = null;
496                    if( isColumnDisplay( headCount+(clmKeys.length-1)*sumCount ) ) {
497                            String temp = clmKeys[clmKeys.length-1];
498                            if( temp == null || temp.length() == 0 ) {
499                                    temp = gokeiLabel;
500                            }
501    
502                            gokeiClm = "<th" + colspan + ">" + temp + "</th>" + HybsSystem.CR ;
503                    }
504    
505                    // 5.2.2.0 (2010/11/01) æœ?¾Œã?カラãƒ?�Œ、合計行ã?
506                    // 5.0.0.3 (2009/09/22) firstClmGokei ã�?trueの場合ã?cubeの先é?に出すよã�?�«しますã?
507    //              if( firstClmGokei && isColumnDisplay( headCount+clmKeys.length-1 ) ) {
508                    if( firstClmGokei && gokeiClm != null ) {
509                            buf.append( gokeiClm );
510                    }
511    
512    //              // 5.0.0.3 (2009/09/22) trueの場合ã?cubeの先é?に出すよã�?�«しますã?
513    //              if( firstClmGokei ){
514    //                      String temp = clmKeys[clmKeys.length-1];
515    //                      if( temp == null || temp.length() == 0 ) {
516    //                              temp = gokeiLabel;
517    //                      }
518    //                      buf.append( "<th").append( colspan ).append( ">" );
519    //                      buf.append( temp );
520    //                      buf.append("</th>").append( HybsSystem.CR );
521    //              }
522    
523                    // 3.7.0.4 (2005/03/18) カラãƒ??列ã?、カラãƒ?•ª号と別物
524                    ResourceManager resource = getResourceManager();
525                    Selection selection = null;
526                    if( headerCode != null && headerCode.length() > 0 && resource != null ){
527                            DBColumn clmTmp = resource.getDBColumn( headerCode );
528                            //selection = new Selection_CODE(resource.getCodeData( headerCode )); code直の場å�?
529                            if ( clmTmp != null ){
530                                    selection = clmTmp.getSelection();
531                            }
532                    }
533    
534                    // 5.7.4.2 (2014/03/20) ヘッãƒ??のリソース適用見直ã�?
535                    // 5.7.4.3 (2014/03/28) useHeaderResource 単独でリソース適用しますã?
536                    DBColumn colClm = null;
537    //              if( useHeaderResource && useHeaderColumn ) {
538                    if( useHeaderResource ) {
539                            colClm = table2.getDBColumn( colClmNo );
540                    }
541    
542                    for( int keyNo = 0; keyNo < clmKeys.length-1; keyNo++ ) {
543                            // 5.2.2.0 (2010/11/01) ColumnDisplay/NoDisplay 対å¿?
544                            if( isColumnDisplay( headCount+keyNo ) ) {
545                                    buf.append( "<th").append( colspan ).append( ">" );
546    //                              if( headerCode != null && headerCode.length() > 0 && selection != null ){
547                                    if( selection != null ){
548                                            buf.append( selection.getValueLabel( clmKeys[keyNo] ) );
549                                    }
550                                    // 5.7.4.2 (2014/03/20) ヘッãƒ??のリソース適用見直ã�?
551    //                              else if( useHeaderResource && useHeaderColumn ){ // 5.5.5.0 (2012/07/28) ヘッãƒ??リソース対å¿?
552    //                                      buf.append( getColumnLabel(headCount+keyNo) );
553    //                              }
554                                    // 5.7.4.3 (2014/03/28) ヘッãƒ??のリソース適用は、CLMカラãƒ??カラãƒ?•ª号のみとしますã?
555                                    else if( colClm != null ) {
556                                            buf.append( colClm.getRendererValue( clmKeys[keyNo] ) );
557                                    }
558                                    else{
559                                            buf.append( clmKeys[keyNo] );
560                                    }
561                                    buf.append("</th>").append( HybsSystem.CR );
562                            }
563                    }
564    
565                    // 5.2.2.0 (2010/11/01) æœ?¾Œã?カラãƒ?�Œ、合計行ã?
566                    // 5.0.0.3 (2009/09/22) firstClmGokei ã�?trueの場合ã?cubeの先é?に出すよã�?�«しますã?
567    //              if( ! firstClmGokei && isColumnDisplay( headCount+clmKeys.length-1 ) ) {
568                    if( ! firstClmGokei && gokeiClm != null ) {
569                            buf.append( gokeiClm );
570                    }
571    
572                    // 3.5.6.2 (2004/07/05) makeCrossTable( DBTableModel table ) に移å‹?
573                    // æœ?µ‚カラãƒ?åˆ?がNULL(空æ–?­—å?)の場合ã?列合計ですã?
574    //              if( ! firstClmGokei ){ // 5.0.0.3 (2009/09/22) falseの場合ã?æœ?µ‚å?に出ã�?
575    //                      String temp = clmKeys[clmKeys.length-1];
576    //                      if( temp == null || temp.length() == 0 ) {
577    //                              temp = gokeiLabel;
578    //                      }
579    //                      buf.append( "<th").append( colspan ).append( ">" );
580    //                      buf.append( temp );
581    //                      buf.append("</th>").append( HybsSystem.CR );
582    //              }
583    
584                    buf.append("</tr>").append( HybsSystem.CR );
585    
586                    if( sumCount > 1 ) {
587                            buf.append("<tr").append(" class=\"row_h\"").append(" >").append( HybsSystem.CR );
588                            int clmCnt = getColumnCount();  // 3.5.5.7 (2004/05/10)
589                            for(int column = headCount; column < clmCnt; column++) {
590                                    if( isColumnDisplay( column ) ) {
591                                            buf.append( "<th>");
592                                            buf.append( getColumnLabel(column) );
593                                            buf.append("</th>").append( HybsSystem.CR );
594                                    }
595                            }
596                            buf.append("</tr>").append( HybsSystem.CR );
597                    }
598    
599                    headerLine = buf.toString();
600                    return headerLine;
601            }
602    
603            /**
604             * クロスé›?¨ˆ結果の DBTableModelオブジェクトを作æ?しますã?
605             *
606             * @og.rev 3.5.4.8 (2004/02/23) paramInit メソãƒ?ƒ‰で、å?期化を行いますã?
607             * @og.rev 3.5.6.3 (2004/07/12) 列ã?ãƒ?ƒ€ーのソート可否のæŒ?®šを追åŠ?
608             * @og.rev 4.0.0.0 (2007/11/27) ヘッãƒ??カラãƒ??エãƒ?‚£ター、レンãƒ?ƒ©ー適用対å¿?
609             * @og.rev 4.3.5.7 (2008/03/22) ↑リソースが存在しなã�??合ã?、ラベルのみ入れ替ã�?
610             * @og.rev 5.2.2.0 (2010/11/01) useHeaderColumn,useClassAdd 属æ?の追åŠ?
611             * @og.rev 5.7.4.3 (2014/03/28) useHeaderColumn の適用条件をã?æœ??のé›?¨ˆカラãƒ??みに変更ã€?
612             *
613             * @param       table   入力もとの DBTableModelオブジェクãƒ?
614             *
615             * @return      DBTableModelオブジェクãƒ?
616             */
617            private DBTableModel makeCrossTable( final DBTableModel table ) {
618                    Set<String> clmData = gatSortAlgorithmSet();
619    
620                    // 列ã?キーとなるカラãƒ??値を取得しますã?
621                    int rowCnt = table.getRowCount();               // 3.5.5.7 (2004/05/10)
622                    for( int row=0; row<rowCnt; row++ ) {
623                            String clm = table.getValue( row,colClmNo );
624                            if( clm.length() > 0 ) { clmData.add( clm ); }
625                    }
626                    // ゼロストリングは、合計行になりますã?で、最後に追åŠ?�—ますã?
627    
628                    // 3.5.6.3 (2004/07/12) ゼロストリングは、合計行になりますã?で、最後に追åŠ?�—ますã?
629    //              clmKeys = new String[ clmData.size() + 1 ];
630    //              clmKeys = clmData.toArray( clmKeys ) ;
631                    clmKeys = clmData.toArray( new String[clmData.size() + 1] ) ;
632    
633                    clmKeys[clmKeys.length-1] = "" ;
634    
635                    int numberOfColumns =  headCount + clmKeys.length * sumCount ;
636    
637                    DBTableModel tableImpl = DBTableModelUtil.newDBTable();
638                    tableImpl.init( numberOfColumns );
639    
640                    // ヘッãƒ??カラãƒ?ROWãƒ??タ含ã‚?は、そのまま、設定しますã?
641                    for(int column=0; column<headCount; column++) {
642                            tableImpl.setDBColumn( column,table.getDBColumn(column) );
643                    }
644    
645                    // 列情報は、合計å?のカラãƒ?®š義を使用しますã?
646                    DBColumn[] dbColumn = new DBColumn[sumCount];
647                    for( int i=0; i<sumCount; i++ ) {
648                            dbColumn[i] = table.getDBColumn(headCount + 1 + i);
649                    }
650    
651                    // 列情報は、å?の名前をカラãƒ??値に変えて、合計カラãƒ??のコピã?æƒ??を設定しますã?
652    
653                    int sumId = 0;
654                    ResourceManager resource = getResourceManager();
655                    useHeaderColumn = useHeaderColumn && resource != null ; // 5.2.2.0 (2010/11/01)
656    
657                    // 5.2.2.0 (2010/11/01) useClassAdd 属æ?の追åŠ?
658    
659                    clsAdd = new String[numberOfColumns];
660    
661                    // 列情報カラãƒ??、ã?ãƒ?ƒ€ーåˆ?�«割り当てられる為ã€?–‹始が、headCount からになりますã?
662                    for(int column=headCount; column<numberOfColumns; column++) {
663                            DBColumn dbClm = dbColumn[sumId];
664                            String clmKey  = clmKeys[ (column-headCount)/sumCount ];
665    
666                            // 5.2.2.0 (2010/11/01) useClassAdd 属æ?の追åŠ?
667                            if( useClassAdd ) {
668                                     // ※ 特殊対応:cssなどでæŒ?®šできるIDやCLASS属æ?は、å?頭æ–?­—が数字ã?場合ã?ã€?
669                                     // 無効になりますã?(つまりã?効きませんã€?
670                                     // 表示ヘッãƒ??は、年月や、社員番号(数å­?などのケースもありますã?そこで、å?頭が数字ã?
671                                     // 場合ã?ã€?x"(小文字ã?x)をè?動的に頭に追åŠ?�—ますã?
672                                    StringBuilder buf = new StringBuilder();
673                                    if( clmKey != null && clmKey.length() > 0 ) {
674                                            char ch = clmKey.charAt(0);
675                                            if( ch >= '0' && ch <= '9' ) {
676                                                    buf.append( "x" );
677                                            }
678                                            buf.append( clmKey );
679                                    }
680    
681                                    String nm = dbClm.getName();
682                                    if( nm != null && nm.length() > 0 ) {
683                                            buf.append( " " );
684                                            char ch = nm.charAt(0);
685                                            if( ch >= '0' && ch <= '9' ) {
686                                                    buf.append( "x" );
687                                            }
688                                            buf.append( nm );
689                                    }
690                                    clsAdd[column] = buf.toString();
691                            }
692    
693                            // 4.0.0.0 (2007/11/27)
694    //                      if( resource != null && "true".equalsIgnoreCase( getParam( "useHeaderColumn", null ) ) ) {
695                            // 5.2.2.0 (2010/11/01) 処ç�?¦‹直しã?useHeaderColumn の前å?しと、setName 対å¿?
696    
697                            // 5.7.4.3 (2014/03/28) useHeaderColumn の適用条件をã?æœ??のé›?¨ˆカラãƒ??みに変更ã€?
698    //                      if( useHeaderColumn ) {
699                            if( useHeaderColumn && sumId == 0 ) {
700    //                              String clmKey = clmKeys[ (column-headCount)/sumCount ]; // 5.2.2.0 (2010/11/01) 上に移å‹?
701                                    DBColumn clmTmp = resource.getDBColumn( clmKey );
702                                    if( clmTmp == null ) {
703    //                                      tableImpl.setDBColumn( column,dbColumn[sumId] ); }
704                                            DBColumnConfig dbCfg2 = dbClm.getConfig();
705                                            if( clmKey != null && clmKey.length() > 0 ) {        // 5.2.2.0 (2010/11/01)
706                                                    dbCfg2.setName( clmKey );
707                                                    dbCfg2.setLabelData( resource.getLabelData( clmKey ) );
708                                            }
709                                            else {
710                                                    dbCfg2.setLabelData( resource.getLabelData( gokeiLabel ) );
711                                            }
712                                            dbClm = new DBColumn( dbCfg2 );
713    //                                      tableImpl.setDBColumn( column, new DBColumn( dbCfg2 ) );
714                                    }
715                                    else {
716    //                                      tableImpl.setDBColumn( column,dbClm );
717                                            dbClm = clmTmp;
718                                    }
719                            }
720    //                      else {
721    //                              tableImpl.setDBColumn( column,dbColumn[sumId] );
722    //                      }
723    
724                            tableImpl.setDBColumn( column,dbClm );
725    
726                            sumId++;
727                            if( sumId % sumCount == 0 ) {
728                                    sumId = 0;
729                            }
730                    }
731    
732                    // クロスé›?¨ˆデータの作æ?
733                    CrossMap cross = new CrossMap( clmKeys,headCount,sumCount );
734                    for( int row=0; row<rowCnt; row++ ) {
735                            String[] data = table.getValues( row );
736                            cross.add( data );
737                    }
738    
739                    // ãƒ??タ部の設å®?
740                    int size = cross.getSize();
741                    for( int row=0; row<size; row++ ) {
742                            tableImpl.addValues( cross.get( row ), row );
743                    }
744    
745                    tableImpl.resetModify();
746    
747                    final DBTableModel model ;
748                    if( gokeiSortDir != null ) {
749                            DBTableModelSorter temp = new DBTableModelSorter();
750                            temp.setModel( tableImpl );
751    
752                            boolean direction = Boolean.valueOf( gokeiSortDir ).booleanValue();
753                            temp.sortByColumn( numberOfColumns-1,direction );
754                            model = temp ;
755                    }
756                    else {
757                            model = tableImpl;
758                    }
759                    return model ;
760            }
761    
762            /**
763             * 列ã?ãƒ?ƒ€ーのソート方法に応じたã?Setオブジェクトを返しますã?
764             * ここでは、NUMBER , STRING , LOAD の?“種類用意してã�?�¾すã?
765             *
766             * @og.rev 3.5.6.3 (2004/07/12) 新規作æ?
767             *
768             * @return      ソート方法に応じたSetオブジェクãƒ?
769             */
770            private Set<String> gatSortAlgorithmSet() {
771                    final Set<String> rtnSet ;
772    
773                    if( "LOAD".equalsIgnoreCase( cubeSortType ) ) {
774                            rtnSet = new LinkedHashSet<String>();
775                    }
776                    else if( "NUMBER".equalsIgnoreCase( cubeSortType ) ) {
777                            rtnSet = new TreeSet<String>( numberSort );
778                    }
779                    else if( "STRING".equalsIgnoreCase( cubeSortType ) ) {
780                            rtnSet = new TreeSet<String>();
781                    }
782                    else {
783                            String errMsg = "cubeSortType は、NUMBER,STRING,LOAD 以外指定できませんã€? +
784                                                            "  cubeSortType=[" + cubeSortType + "]";
785                            throw new HybsSystemException( errMsg );
786                    }
787    
788                    return rtnSet ;
789            }
790    
791            /**
792             * 表示不可カラãƒ?��をã?カンマ区åˆ?‚Šで与えますã?
793             * 例ï¼?OYA,KO,HJO,SU,DYSET,DYUPD"
794             * null を与えたå?合ã?,なにもしませんã€?
795             *
796             * 注意:このクラスでは、DBTableModel を作り直すタイミングがã?
797             * create メソãƒ?ƒ‰実行時ですã?(パラメータの初期化がå¿?¦�な為)
798             * よって、このメソãƒ?ƒ‰は、å?期が終äº?¾Œに、å?セãƒ?ƒˆしますã?
799             *
800             * @og.rev 3.7.0.4 (2005/03/18) 新規作æ?
801             *
802             * @param       columnName      カラãƒ?��
803             */
804            @Override
805            public void setNoDisplay( final String columnName ) {
806                    noDisplayKeys = columnName;
807            }
808    
809            /**
810             * 表示可能カラãƒ?��をã?カンマ区åˆ?‚Šで与えますã?
811             * 例ï¼?OYA,KO,HJO,SU,DYSET,DYUPD"
812             * setColumnDisplay( int column,boolean rw ) の簡易版ですã?
813             * null を与えたå?合ã?,なにもしませんã€?
814             * またã?全カラãƒ?�«つã�?�¦、有効にする場合ã?、columnName="*" を設定しますã?
815             *
816             * @og.rev 5.2.2.0 (2010/11/01) 新規追åŠ?
817             *
818             * @param       columnName      カラãƒ?��
819             */
820            @Override
821            public void setColumnDisplay( final String columnName ) {
822                    columnDisplayKeys = columnName;
823            }
824    
825            /**
826             * NUMBER ソート機è?(整数限å®? å†?ƒ¨クラス
827             * これは通常のソートではなくã?ヘッãƒ??に使ã�?ƒ©ベルのソートなのでã€?
828             * 整数のみと限定しますã?実数の場合ã?、桁合わせ(小数点以下ã?桁数)
829             * されてã�?‚‹とã�?�†前提ですã?
830             *
831             * @og.rev 3.5.6.3 (2004/07/12) 新規作æ?
832             *
833             */
834            private static final Comparator<String> numberSort = new NumberComparator();
835    
836            private static class NumberComparator implements Comparator<String>,Serializable {
837                    private static final long serialVersionUID = 4000 ;     // 4.0.0 (2005/01/31)
838    
839                    public int compare( final String s1, final String s2 ) {
840                            if( s1.length() > s2.length() )      { return 1;  }
841                            else if( s1.length() < s2.length() ) { return -1; }
842                            else {
843                                    return s1.compareTo( s2 );
844                            }
845                    }
846            }
847    
848            /**
849             * 表示é ?›®の編é›?並び替ã�?が可能かどã�?�‹を返しまã�?
850             *
851             * @og.rev 5.1.6.0 (2010/05/01) 新規追åŠ?
852             *
853             * @return      表示é ?›®の編é›?並び替ã�?が可能かどã�?�‹(false:不可能)
854             */
855            @Override
856            public boolean isEditable() {
857                    return false;
858            }
859    }