001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.hayabusa.db;
017
018import java.math.BigDecimal;
019import java.sql.ResultSet;
020import java.sql.ResultSetMetaData;
021import java.sql.SQLException;
022import java.text.DecimalFormat;
023import java.util.ArrayList;
024import java.util.HashMap;
025import java.util.LinkedHashMap;
026import java.util.List;
027import java.util.Locale;
028import java.util.Map;
029
030import org.opengion.fukurou.db.DBUtil;
031import org.opengion.fukurou.util.StringUtil;
032import org.opengion.hayabusa.common.HybsSystem;
033import org.opengion.hayabusa.common.HybsSystemException;
034import org.opengion.hayabusa.resource.LabelData;
035import 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 */
059public 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         * 集計キーが検索順により散在した場合でも1まとまりで集計されます。
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() を先に判定すると必ず1件読み飛ばしてしまう。
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() を先に判定すると必ず1件読み飛ばしてしまう。
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}