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.hayabusa.db;
017    
018    import java.math.BigDecimal;
019    import java.sql.ResultSet;
020    import java.sql.ResultSetMetaData;
021    import java.sql.SQLException;
022    import java.text.DecimalFormat;
023    import java.util.ArrayList;
024    import java.util.HashMap;
025    import java.util.LinkedHashMap;
026    import java.util.List;
027    import java.util.Locale;
028    import java.util.Map;
029    
030    import org.opengion.fukurou.db.DBUtil;
031    import org.opengion.fukurou.util.StringUtil;
032    import org.opengion.hayabusa.common.HybsSystem;
033    import org.opengion.hayabusa.common.HybsSystemException;
034    import org.opengion.hayabusa.resource.LabelData;
035    import org.opengion.hayabusa.resource.ResourceManager;
036    
037    /**
038     * DBTableModelを継承した TableModelの編é›?¨­定による変換を行うための実è£?‚¯ラスですã?
039     *
040     * こã?クラスでは、オブジェクトå?期化後ã?ã€??常のDBTableModelと同じ振るè?ã�?‚’しますã?
041     * オブジェクトå?期化æ™?createメソãƒ?ƒ‰呼び出し時)に、検索結果オブジェクトから直接、編é›?¨­定に
042     * 応じて変換されたDBTableModelを生成しますã?
043     *
044     * こã?ような実è£?‚’行うç�?”±は、メモリ使用量をç¯?´?�™るためですã?
045     * こã?編é›?¨­定ではã€?›†計機è?を備えてã�?�¾すが、ä¸?—¦DBTableModel作æ?後にé›?¨ˆå?ç�?‚’行うとã€?
046     * メモリを大量に使用する恐れがあるためã?検索結果オブジェクトから直接é›?¨ˆå?ç�?‚’行い、DBTableModelã‚?
047     * 生æ?してã�?�¾すã?
048     *
049     * DBTableModel インターフェースは?Œデータベã?スの検索結果(Resultset)をラãƒ??する
050     * インターフェースとして使用して下さã�??
051     *
052     * @og.rev 5.3.6.0 (2011/06/01) 新規作æ?
053     * @og.group ãƒ??ブル管ç�?
054     *
055     * @version  5.0
056     * @author   Hiroki Nakamura
057     * @since    JDK6.0,
058     */
059    public class DBTableModelEditor extends DBTableModelImpl {
060            private static final String JS                          = HybsSystem.JOINT_STRING;
061            private static final DecimalFormat FORMAT       = new DecimalFormat( "0.#########" );
062    
063            private int rowCountColumn = -1;
064            private DBEditConfig config;
065    
066            /**
067             * DBTableModel を設定し、このオブジェクトを初期化しますã?
068             *
069             * @og.rev 5.7.1.2 (2013/12/20) msg â‡?errMsg 変更
070             * @og.rev 5.8.2.0 (2014/12/05) 合計時のエラーチェãƒ?‚¯追åŠ?
071             *
072             * @param       result                  検索結果オブジェクãƒ?
073             * @param       skipRowCount    読み飛ã?し件数
074             * @param       maxRowCount             æœ?¤§検索件数
075             * @param       resource                ResourceManagerオブジェクãƒ?
076             * @param       config                  エãƒ?‚£ãƒ?ƒˆ設定オブジェクãƒ?
077             * @throws      SQLException ãƒ??タベã?スアクセスエラー
078             */
079            public void create( final ResultSet result, final int skipRowCount, final int maxRowCount, final ResourceManager resource, final DBEditConfig config ) throws SQLException {
080                    if( result == null || config == null || resource == null ) {
081    //                      String msg = "DBTableModelまたã?、DBEditConfigが設定されてã�?�¾せんã€?;
082    //                      throw new HybsSystemException( msg );
083                            String errMsg = "DBTableModelまたã?、DBEditConfigが設定されてã�?�¾せんã€?;
084                            throw new HybsSystemException( errMsg );        // 5.7.1.2 (2013/12/20) msg â‡?errMsg 変更
085                    }
086    
087                    this.config = config;
088    
089                    /**********************************************************************
090                     * å�?ƒ‘ラメーターの初期化å?ç�?
091                     **********************************************************************/
092                    ResultSetMetaData metaData      = result.getMetaData();
093                    int colCnt = metaData.getColumnCount();
094                    if( config.useGroup() || config.useSubTotal() || config.useTotal() || config.useGrandTotal() ) {
095                            rowCountColumn = colCnt;
096                            colCnt++;
097                    }
098                    init( colCnt );
099    
100                    DBColumn[] dbColumn = new DBColumn[numberOfColumns];
101                    int[] types  = new int[numberOfColumns];
102                    boolean[] sumFilter = new boolean[numberOfColumns];
103                    boolean[] groupFilter = new boolean[numberOfColumns];
104                    boolean[] subTotalFilter = new boolean[numberOfColumns];
105                    boolean[] totalFilter = new boolean[numberOfColumns];
106                    boolean   sumFilterCheck        = false;                                                // 5.8.2.0 (2014/12/05)
107                    if( config.useGrandTotal() ) { sumFilterCheck = true; }         // 5.8.2.1 (2014/12/13)
108                    for( int column=0; column<numberOfColumns; column++ ) {
109                            String name = null;
110                            if( column != rowCountColumn ) {
111                                    name = (metaData.getColumnLabel(column+1)).toUpperCase(Locale.JAPAN);
112                                    types[column] = metaData.getColumnType(column+1);
113                                    dbColumn[column] = resource.getDBColumn( name );
114                                    if( dbColumn[column] == null ) {
115                                            LabelData labelData  = resource.getLabelData( name );
116                                            dbColumn[column] = DBTableModelUtil.makeDBColumn( name,labelData,metaData,column,resource.getLang() );
117                                    }
118                            }
119                            else {
120                                    name = "rowCount";
121                                    dbColumn[column] = resource.makeDBColumn( name );
122                            }
123    
124                            setDBColumn( column,dbColumn[column] );
125    
126                            sumFilter[column] = config.isSumClm( name );
127                            groupFilter[column] = config.isGroupClm( name );
128                            subTotalFilter[column] = config.isSubTotalClm( name );
129                            totalFilter[column] = config.isTotalClm( name );
130                            
131                            //5.8.2.0 (2014/12/05) チェãƒ?‚¯追åŠ?
132                            if( sumFilter[column] || groupFilter[column] || subTotalFilter[column] || totalFilter[column] ) {
133                                    sumFilterCheck = true;
134                            }
135                    }
136    
137                    /**********************************************************************
138                     * é›?¨ˆã?ソートã?合計å?ç�?
139                     **********************************************************************/
140                    // é›?¨ˆキーに基づく集計å?ç�?‚’行いãƒ??タを追åŠ?�—ますã?
141                    if( config.useGroup() ) {
142                            addGroupRows( result, types, skipRowCount, maxRowCount, sumFilter, groupFilter  );
143                    }
144                    // 通常と同じように結果カーソルからãƒ??タを読込みãƒ??タを追åŠ?�—ますã?
145                    else {
146                            // 5.5.2.4 (2012/05/16) int[] types は使われてã�?�ªã�??で、削除しますã?
147    //                      addPlainRows( result, types, skipRowCount, maxRowCount );
148                            addPlainRows( result, skipRowCount, maxRowCount );
149                    }
150    
151                    // ソートå?ç�?
152                    if( getRowCount() > 0 && config.useOrderBy() ) {
153                            sort();
154                    }
155    
156                    // 小計ã?合計行を追åŠ?�—ますã?
157                    if( getRowCount() > 0 && !isOverflow()
158                            && ( config.useSubTotal() || config.useTotal() || config.useGrandTotal() ) ) {
159                            
160                            // 5.8.2.0 (2014/12/05) queryタグがè¤?•°あり、mainTrans=false で制御されてã�?�ªã�??合ã?エラーが発生すã‚?
161                            if( !sumFilterCheck ) {
162                                    String errMsg = "小計ã?合計カラãƒ?�Œ存在しませんã€?
163                                                                    + " これは、queryタグがè¤?•°あり、mainTrans=false で制御されてã�?�ªã�?�¯能性がありますã?" ;
164                                    throw new HybsSystemException( errMsg );
165                            }
166                            
167                            addTotalRows( maxRowCount, resource, sumFilter, groupFilter, subTotalFilter, totalFilter );
168                    }
169            }
170    
171            /**
172             * é›?¨ˆキーの設定に基づきã?DBTableModelの行を追åŠ?�—ますã?
173             * å†?ƒ¨çš?�«は、キーブレイクではなくã?å†?ƒ¨マップによりé›?¨ˆå?ç�?‚’行ってã�?‚‹ためã€?
174             * é›?¨ˆキーが検索é ?�«より散在した場合でã‚?まとまりでé›?¨ˆされますã?
175             *
176             * @og.rev 5.3.9.0 (2011/09/01) 値がNULLの場合にエラーになるバグを修正
177             * @og.rev 5.6.1.0 (2013/02/01) doubleをBigDecimalに
178             *
179             * @param result 検索結果オブジェクãƒ?
180             * @param types カラãƒ?‚¿イプã?配å?
181             * @param skipRowCount 読み飛ã?し件数
182             * @param maxRowCount æœ?¤§検索件数
183             * @param sumFilter é›?¨ˆé?目フィルター
184             * @param groupFilter グループキーフィルター
185             * @throws SQLException ãƒ??タベã?スアクセスエラー
186             */
187            private void addGroupRows( final ResultSet result, final int[] types, final int skipRowCount, final int maxRowCount
188                                                                    , final boolean[] sumFilter, final boolean[] groupFilter ) throws SQLException {
189                    int numberOfRows = 0;
190                    while( numberOfRows < skipRowCount && result.next() ) {
191                            // 注æ„?resultSet.next() をå?に判定するとå¿?�š?‘件読み飛ã?してしまã�??
192                            numberOfRows ++ ;
193                    }
194                    numberOfRows = 0;
195    
196                    Map<String,String[]> groupLinkedMap = new LinkedHashMap<String,String[]>();
197                    Map<String,Integer> groupCountMap = new HashMap<String,Integer>();
198    //              Map<String,double[]> sumMap = new HashMap<String,double[]>();
199                    Map<String,BigDecimal[]> sumMap = new HashMap<String,BigDecimal[]>(); // 5.6.1.0 (2013/02/01)
200                    while( numberOfRows < maxRowCount && result.next() ) {
201                            StringBuilder groupKey = new StringBuilder();
202    //                      double[] sumVals = new double[config.getSumClmCount()];
203                            BigDecimal[] sumVals = new BigDecimal[config.getSumClmCount()]; // 5.6.1.0 (2013/02/01) 
204                            String[] groupVals = new String[config.getGroupClmCount()];
205                            int sc = 0;
206                            int gc = 0;
207                            for( int column=0; column<numberOfColumns; column++ ) {
208                                    if( column != rowCountColumn ) {
209                                            String val = DBUtil.getValue( result, column, types[column] );
210                                            if( sumFilter[column] ) {
211                                                    // 5.3.9.0 (2011/09/01) 値がNULLの場合ã?対応漏れ
212    //                                              sumVals[sc++] = Double.valueOf( val );
213                                                    // sumVals[sc++] = ( val != null && val.length() > 0 ? Double.valueOf( val ) : 0 );
214                                                    sumVals[sc++] = ( val != null && val.length() > 0 ? new BigDecimal( val ) : new BigDecimal(0) ); // 5.6.1.0 (2013/02/01)
215                                            }
216                                            if( groupFilter[column] ) {
217                                                    groupVals[gc++] = val;
218                                                    groupKey.append( val ).append( JS );
219                                            }
220                                    }
221                            }
222    
223                            String key = groupKey.toString();
224                            int groupCount = 0;
225                            if( groupLinkedMap.containsKey( key ) ) {
226    //                              double[] eSumVals = sumMap.get( key );
227                                    BigDecimal[] eSumVals = sumMap.get( key ); // 5.6.1.0 (2013/02/01)
228                                    for( int i=0; i<config.getSumClmCount(); i++ ) {
229    //                                      sumVals[i] += eSumVals[i];
230                                            sumVals[i] = sumVals[i] == null ? new BigDecimal(0) : sumVals[i].add( eSumVals[i] ); // 5.6.1.0 (2013/02/01)
231                                    }
232                                    sumMap.put( key, sumVals );
233                                    groupCount = groupCountMap.get( key ).intValue() + 1;
234                            }
235                            else {
236                                    groupLinkedMap.put( key, groupVals );
237                                    groupCount = 1;
238                                    numberOfRows++;
239                            }
240                            sumMap.put( key, sumVals );
241                            groupCountMap.put( key, Integer.valueOf( groupCount ) );
242                    }
243    
244                    for( Map.Entry<String, String[]> entry : groupLinkedMap.entrySet() ) {
245                            String key = entry.getKey();
246                            addRow( groupFilter, entry.getValue(), groupCountMap.get( key ), sumFilter, sumMap.get( key ) );
247                    }
248    
249                    // æœ?¤§件数がã?è¶?�ˆたå?合でかつ次のãƒ??タがあるå?合ã?、オーバã?フロー
250                    if( numberOfRows >= maxRowCount && result.next() ) {
251                            setOverflow( true );
252                    }
253            }
254    
255            /**
256             * 検索結果オブジェクトをé ?�«読み取り、そのままDBTableModelの行を追åŠ?�—ますã?
257             *
258             * @og.rev 5.5.2.4 (2012/05/16) int[] types は使われてã�?�ªã�??で、削除しますã?
259             *
260             * @param result 検索結果オブジェクãƒ?
261             * @param skipRowCount 読み飛ã?し件数
262             * @param maxRowCount æœ?¤§検索件数
263             * @throws      SQLException ãƒ??タベã?スアクセスエラー
264             */
265    //      private void addPlainRows( final ResultSet result, final int[] types, final int skipRowCount, final int maxRowCount ) throws SQLException {
266            private void addPlainRows( final ResultSet result, final int skipRowCount, final int maxRowCount ) throws SQLException {
267                    int numberOfRows = 0;
268                    while( numberOfRows < skipRowCount && result.next() ) {
269                            // 注æ„?resultSet.next() をå?に判定するとå¿?�š?‘件読み飛ã?してしまã�??
270                            numberOfRows ++ ;
271                    }
272                    numberOfRows = 0;
273    
274                    while( numberOfRows < maxRowCount && result.next() ) {
275                            numberOfRows++ ;
276                            String[] columnValues = new String[numberOfColumns];
277                            for( int column=0; column<numberOfColumns; column++ ) {
278                                    if( column != rowCountColumn ) {
279                                            Object obj = result.getObject(column+1);
280                                            columnValues[column] = ( obj == null ? "" : String.valueOf( obj ) );
281                                    }
282                                    else {
283                                            columnValues[column] = "";
284                                    }
285                            }
286                            addColumnValues( columnValues );
287                    }
288    
289                    // æœ?¤§件数がã?è¶?�ˆたå?合でかつ次のãƒ??タがあるå?合ã?、オーバã?フロー
290                    if( numberOfRows >= maxRowCount && result.next() ) {
291                            setOverflow( true );
292                    }
293            }
294    
295            /**
296             * DBTableModelのソートå?ç�?‚’行いますã?
297             *
298             */
299            private void sort() {
300                    // orderByClmsによる並び替ã�?
301                    DBTableModelSorter temp = new DBTableModelSorter();
302                    temp.setModel( this );
303                    String[] oClms = StringUtil.csv2Array( config.getOrderByClms() );
304                    for( int i=oClms.length-1; i>=0; i-- ) {
305                            String oc = oClms[i];
306                            boolean ascending = true;
307                            if( oc.startsWith( "!" ) ) {
308                                    oc = oc.substring( 1 );
309                                    ascending = false;
310                            }
311                            int clmNo = getColumnNo( oc );
312                            temp.sortByColumn( clmNo, ascending );
313                    }
314                    this.data = temp.data;
315                    this.rowHeader = temp.rowHeader;
316            }
317    
318            /**
319             * DBTableModelからãƒ??タを読み取り、エãƒ?‚£ãƒ?ƒˆ設定情報をå?に合計行ã?追åŠ??ç�?‚’行いますã?
320             * 合計行ã?追åŠ??、キーブレイクにより行われますã?で、同じキーがè¤?•°回å?現した場合ã?ã€?
321             * それぞれの行に対して、合計行が付加されますã?
322             *
323             * @og.rev 5.3.7.0 (2011/07/01) 小計ã?合計行追åŠ??ç�?�§オーバã?フローフラグがセãƒ?ƒˆされなã�?ƒ�グを修正
324             * @og.rev 5.6.1.0 (2013/02/01) 誤差回避のため、doubleではなくdecimalで計算すã‚?
325             * @og.rev 5.6.8.1 (2013/09/13) 1行目が合計されてã�?�ªかったã?で修正
326             * @og.rev 5.8.2.0 (2014/12/05) エラー対å¿?
327             *
328             * @param       maxRowCount æœ?¤§検索件数
329             * @param       resource リソースマネージャー
330             * @param       sumFilter é›?¨ˆé?目フィルター
331             * @param       groupFilter グループキーフィルター
332             * @param       subTotalFilter 小計キーフィルター
333             * @param       totalFilter 合計キーフィルター
334             *
335             * @return      オーバã?フローしたかどã�?�‹(æœ?¤§件数がè¶?�ˆたå?合でかつ次のãƒ??タがあるå?合ã?、true)
336             */
337            private boolean addTotalRows( final int maxRowCount, final ResourceManager resource, final boolean[] sumFilter
338                                                                            ,  final boolean[] groupFilter, final boolean[] subTotalFilter,  final boolean[] totalFilter ) {
339    
340                    String subTotalLabel = ( config.useSubTotal() ? resource.makeDBColumn( "EDIT_SUBTOTAL_VALUE" ).getLongLabel() : null );
341                    String totalLabel = ( config.useTotal() ? resource.makeDBColumn( "EDIT_TOTAL_VALUE" ).getLongLabel() : null );
342                    String grandTotalLabel = ( config.useGrandTotal() ? resource.makeDBColumn( "EDIT_GRANDTOTAL_VALUE" ).getLongLabel() : null );
343    
344                    int numberOfRows = getRowCount();
345                    int sumClmCount = config.getSumClmCount();
346    //              double subTotalSum[] = new double[sumClmCount];
347    //              double totalSum[] = new double[sumClmCount];
348    //              double grandTotalSum[] = new double[sumClmCount];
349                    BigDecimal subTotalSum[] = new BigDecimal[sumClmCount]; // 5.6.1.0 (2013/02/01)
350                    BigDecimal totalSum[] = new BigDecimal[sumClmCount];
351                    BigDecimal grandTotalSum[] = new BigDecimal[sumClmCount];
352    
353                    String lastSubTotalKey = null;
354                    String lastTotalKey = null;
355    
356                    int subTotalCount = 0;
357                    int totalCount = 0;
358                    int grandTotalCount = 0;
359                    int rowCount =0;
360    
361                    int tblIdx = 0;
362                    while( numberOfRows < maxRowCount && tblIdx < getRowCount() ) {
363    //                      double[] sumVals = new double[sumClmCount];
364                            BigDecimal[] sumVals = new BigDecimal[sumClmCount]; // 5.6.1.0 (2013/02/01)
365                            StringBuilder groupKey = new StringBuilder();
366                            StringBuilder subTotalKey = new StringBuilder();
367                            StringBuilder totalKey = new StringBuilder();
368    
369                            int sc = 0;
370                            for( int column=0; column<numberOfColumns; column++ ) {
371                                    String val = getValue( tblIdx, column );
372                                    if( groupFilter[column] )               { groupKey.append( val ).append( JS ); }
373    //                              if( sumFilter[column] )                 { sumVals[sc++] = ( val != null && val.length() > 0 ? Double.valueOf( val ) : 0 ); }
374                                    if( sumFilter[column] )                 { sumVals[sc++] = ( val != null && val.length() > 0 ? new BigDecimal( val ) : new BigDecimal(0) ); } // 5.6.1.0 (2013/02/01)
375                                    if( subTotalFilter[column] )    { subTotalKey.append( val ).append( JS ); }
376                                    if( totalFilter[column] )               { totalKey.append( val ).append( JS ); }
377    //                              if( column == rowCountColumn )  { rowCount = ( val != null && val.length() > 0 ? Integer.valueOf( val ) : 0 ); }
378                                    if( column == rowCountColumn )  { rowCount = ( val != null && val.length() > 0 ? Integer.parseInt( val ) : 0 ); } // 5.8.2.0 (2014/12/05) メソãƒ?ƒ‰変更
379                            }
380    
381                            // 小計キーブレイク処ç�?
382                            if( numberOfRows < maxRowCount && config.useSubTotal() && lastSubTotalKey != null && lastSubTotalKey.length() > 0
383                                    && !lastSubTotalKey.equals( subTotalKey.toString() ) ) {
384                                    addRow( subTotalFilter, subTotalLabel, subTotalCount, sumFilter, subTotalSum, tblIdx );
385    //                              subTotalSum = new double[sumClmCount];
386                                    subTotalSum = new BigDecimal[sumClmCount]; // 5.6.1.0 (2013/02/01)
387                                    subTotalCount = 0;
388                                    numberOfRows++;
389                                    tblIdx++;
390                            }
391    
392                            // 合計キーブレイク処ç�?
393                            if( numberOfRows < maxRowCount && config.useTotal() && lastTotalKey != null && lastTotalKey.length() > 0
394                                    && !lastTotalKey.equals( totalKey.toString() ) ) {
395                                    addRow( totalFilter, totalLabel, totalCount, sumFilter, totalSum, tblIdx );
396    //                              totalSum = new double[sumClmCount];
397                                    totalSum = new BigDecimal[sumClmCount]; // 5.6.1.0 (2013/02/01)
398                                    totalCount = 0;
399                                    numberOfRows++;
400                                    tblIdx++;
401                            }
402    
403                            // 小計ã?合計ã?総合計単位にé›?¨ˆé?目の合計å?を加算しますã?
404                            // 6.0.2.0 (2014/09/19) BigDecimal.ZERO.add で、null エラーが発生するã?は、query がè¤?•°あり、mainTrans=false で制御されてã�?�ªã�??å�?
405    //                      for( int cnt=0; cnt<sumClmCount; cnt++ ) {
406                            for( int cnt=0; cnt<sc; cnt++ ) {
407                                    subTotalSum[cnt] = subTotalSum[cnt] == null ? new BigDecimal(0).add(sumVals[cnt]) : subTotalSum[cnt].add(sumVals[cnt]); // 5.6.8.1 (2013/09/13)
408                                    totalSum[cnt] = totalSum[cnt] == null ? new BigDecimal(0).add(sumVals[cnt]) : totalSum[cnt].add(sumVals[cnt]);
409                                    grandTotalSum[cnt] = grandTotalSum[cnt] == null ? new BigDecimal(0).add(sumVals[cnt]) : grandTotalSum[cnt].add(sumVals[cnt]);
410    
411                            }
412    
413                            lastSubTotalKey = subTotalKey.toString();
414                            lastTotalKey = totalKey.toString();
415    
416                            // グループ集計時はグルーピングした行数を加算するã?
417                            int gcnt = 1;
418                            if( config.useGroup() && rowCountColumn >= 0 && rowCount > 0 ) {
419                                    gcnt = rowCount;
420                            }
421                            subTotalCount += gcnt;
422                            totalCount    += gcnt;
423                            grandTotalCount += gcnt;
424    
425                            tblIdx++;
426                    }
427    
428                    // æœ?¤§件数がã?è¶?�ˆたå?合でかつ次のãƒ??タがあるå?合ã?、オーバã?フロー
429                    boolean isOverFlow = ( tblIdx < getRowCount() );
430    
431                    // 小計キーæœ?µ‚行å?ç�?
432                    if( config.useSubTotal() && lastSubTotalKey != null ) {
433                            if( numberOfRows < maxRowCount ) {
434                                    addRow( subTotalFilter, subTotalLabel, subTotalCount, sumFilter, subTotalSum, tblIdx );
435                                    numberOfRows++;
436                                    tblIdx++;
437                            }
438                            else {
439                                    isOverFlow = true;
440                            }
441                    }
442    
443                    // 合計キーæœ?µ‚行å?ç�?
444                    if( config.useTotal() && lastTotalKey != null ) {
445                            if( numberOfRows < maxRowCount ) {
446                                    addRow( totalFilter, totalLabel, totalCount, sumFilter, totalSum, tblIdx );
447                                    numberOfRows++;
448                                    tblIdx++;
449                            }
450                            else {
451                                    isOverFlow = true;
452                            }
453                    }
454    
455                    // 総合計å?ç�?
456                    if( config.useGrandTotal() && numberOfRows > 0 ) {
457                            if( numberOfRows < maxRowCount ) {
458                                    boolean[] grandTotalFilter = new boolean[numberOfColumns];
459                                    // 総合計ã?ラベル表示å»?­¢
460                                    // grandTotalFilter[0] = true;
461                                    addRow( grandTotalFilter, grandTotalLabel, grandTotalCount, sumFilter, grandTotalSum, tblIdx );
462                                    numberOfRows++;
463                                    tblIdx++;
464                            }
465                            else {
466                                    isOverFlow = true;
467                            }
468                    }
469    
470                    if( isOverFlow ) {
471                            setOverflow( true );
472                    }
473    
474                    return isOverFlow;
475            }
476    
477            /**
478             * キーの値配å?ã€?›†計å?の配å?を引数として、追åŠ?¡Œを生æ?しã?DBTableModelに追åŠ?�—ますã?
479             * キー、及びé›?¨ˆå?がDBTableModel上ã?どのカラãƒ?�«位置するかã?、キーフィルタã€?›†計フィルタでæŒ?®šしますã?
480             * 
481             * @og.rev 5.6.1.0 (2013/02/01) doubleをdecimalに
482             *
483             * @param keyFilter キーフィルタ
484             * @param keyVals キーの値配å?
485             * @param keyCount é›?¨ˆした行ã?カウンãƒ?
486             * @param sumFilter é›?¨ˆフィルタ
487             * @param sumVals é›?¨ˆå?配å?
488             * @param aRow 挿入する行番号
489             */
490    //      private void addRow( final boolean[] keyFilter, final String[] keyVals, final int keyCount
491    //                                                      , final boolean[] sumFilter, final double[] sumVals, final int aRow ) {
492            private void addRow( final boolean[] keyFilter, final String[] keyVals, final int keyCount
493                            , final boolean[] sumFilter, final BigDecimal[] sumVals, final int aRow ) {
494                    String[] columnValues = new String[numberOfColumns];
495                    int sc = 0;
496                    int kc = 0;
497                    for( int column=0; column<numberOfColumns; column++ ) {
498                            String val = "";
499                            if( keyFilter[column] ) {
500                                    val = keyVals[kc++];
501                            }
502                            if( sumFilter[column] ) {
503                                    val = FORMAT.format( sumVals[sc++] ) ;
504                            }
505                            if( column == rowCountColumn ) {
506                                    val = String.valueOf( keyCount );
507                            }
508                            columnValues[column] = val;
509                    }
510                    
511                    if( aRow < 0 ) {
512                            addColumnValues( columnValues );
513                    }
514                    else {
515                            addValues( columnValues, aRow, false );
516                    }
517            }
518    
519            /**
520             * キーの値配å?ã€?›†計å?の配å?を引数として、追åŠ?¡Œを生æ?しã?DBTableModelに追åŠ?�—ますã?
521             * キー、及びé›?¨ˆå?がDBTableModel上ã?どのカラãƒ?�«位置するかã?、キーフィルタã€?›†計フィルタでæŒ?®šしますã?
522             * 
523             * @og.rev 5.6.1.0 (2013/02/01) doubleをbigDecimal
524             *
525             * @param keyFilter キーフィルタ
526             * @param keyVals キーの値配å?
527             * @param keyCount é›?¨ˆした行ã?カウンãƒ?
528             * @param sumFilter é›?¨ˆフィルタ
529             * @param sumVals é›?¨ˆå?配å?
530             */
531    //      private void addRow( final boolean[] keyFilter, final String[] keyVals, final int keyCount
532    //                                                      , final boolean[] sumFilter, final double[] sumVals ) {
533            private void addRow( final boolean[] keyFilter, final String[] keyVals, final int keyCount
534                            , final boolean[] sumFilter, final BigDecimal[] sumVals ) {
535                    addRow( keyFilter, keyVals, keyCount, sumFilter, sumVals, -1 );
536            }
537    
538            /**
539             * キーの値ã€?›†計å?の配å?を引数として、追åŠ?¡Œを生æ?しã?DBTableModelに追åŠ?�—ますã?
540             * キー、及びé›?¨ˆå?がDBTableModel上ã?どのカラãƒ?�«位置するかã?、キーフィルタã€?›†計フィルタでæŒ?®šしますã?
541             * 
542             * @og.rev 5.6.1.0 (2013/02/01) doubleをbigDecimalに
543             *
544             * @param keyFilter キーフィルタ
545             * @param keyVal キーの値
546             * @param keyCount é›?¨ˆした行ã?カウンãƒ?
547             * @param sumFilter é›?¨ˆフィルタ
548             * @param sumVals é›?¨ˆå?配å?
549             * @param aRow 挿入する行番号
550             */
551    //      private void addRow( final boolean[] keyFilter, final String keyVal, final int keyCount
552    //                                                      , final boolean[] sumFilter, final double[] sumVals, final int aRow ) {
553            private void addRow( final boolean[] keyFilter, final String keyVal, final int keyCount
554                            , final boolean[] sumFilter, final BigDecimal[] sumVals, final int aRow ) {
555                    List<String> tmp = new ArrayList<String>();
556                    for( int column=0; column<numberOfColumns; column++ ) {
557                            if( keyFilter[column] ) {
558                                    tmp.add( keyVal );
559                            }
560                    }
561    //              addRow( keyFilter, tmp.toArray( new String[0] ), keyCount, sumFilter, sumVals, aRow );
562                    addRow( keyFilter, tmp.toArray( new String[tmp.size()] ), keyCount, sumFilter, sumVals, aRow );
563            }
564    }