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 org.opengion.fukurou.util.StringUtil;
019import org.opengion.fukurou.model.NativeType;
020import org.opengion.hayabusa.common.HybsSystem;
021import org.opengion.hayabusa.common.HybsSystemException;
022
023import java.util.List;
024import java.util.ArrayList;
025import java.util.Map;
026import java.util.HashMap;
027import java.util.Set;
028import java.util.HashSet;
029import java.util.Arrays;
030import java.util.Locale ;
031
032/**
033 * DBTableModel インターフェースを継承した TableModel の実装クラスです。
034 * sql文を execute( query ) する事により,データベースを検索した結果を
035 * DBTableModel に割り当てます。
036 *
037 * メソッドを宣言しています
038 * DBTableModel インターフェースは,データベースの検索結果(Resultset)をラップする
039 * インターフェースとして使用して下さい。
040 *
041 * @og.group テーブル管理
042 *
043 * @version  4.0
044 * @author   Kazuhiko Hasegawa
045 * @since    JDK5.0,
046 */
047public class DBTableModelImpl implements DBTableModel {
048        /** カラムオブジェクト配列 */
049        protected       DBColumn[]                      dbColumns       = null;
050        /** カラム名称配列 */
051        protected       String[]                        names           = null;
052        /** テータリスト */
053        protected       List<String[]>          data            = null;
054        /** 行ヘッダー情報 */
055        protected       List<DBRowHeader>       rowHeader       = null;
056        /** カラムアドレスマップ情報 */
057        protected       Map<String,Integer> columnMap   = null;
058        /** オーバーフローフラグ */
059        protected       boolean                         overflow        = false;
060
061        /** カラム数 */
062        protected   int         numberOfColumns = 0;
063
064        // 3.5.5.5 (2004/04/23) 整合性キー(オブジェクトの作成時刻)追加
065        /** 整合性キー(オブジェクトの作成時刻) */
066        protected       String          consistencyKey  = String.valueOf( System.currentTimeMillis() );
067        private         String[]        lastData                = null;
068        private         int             lastRow                 = -1;
069
070        // 4.1.2.1 (2008/03/13) カラム(列)にmustタイプ値を割り当てます。
071        private final   Map<String,Set<String>> mustMap = new HashMap<String,Set<String>>() ;   // 4.3.1.1 (2008/08/23) final化
072
073        /**
074         * このオブジェクトを初期化します。
075         * 指定の引数分の内部配列を作成します。
076         *
077         * @og.rev 3.1.0.0 (2003/03/20) 実装を、Vector ,Hashtable から、ArrayList ,HashMapに、変更。
078         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
079         *
080         * @param   columnCount カラム数
081         */
082        public void init( final int columnCount ) {
083                data                    = new ArrayList<String[]>( HybsSystem.BUFFER_MIDDLE );
084                rowHeader               = new ArrayList<DBRowHeader>( HybsSystem.BUFFER_MIDDLE );
085                names                   = new String[columnCount];
086                dbColumns               = new DBColumn[ columnCount ];
087                numberOfColumns = columnCount;
088                columnMap               = new HashMap<String,Integer>();
089                lastRow                 = -1;                           // 3.5.5.7 (2004/05/10)
090        }
091
092        /**
093         * このオブジェクトをヘッダー部分をコピーし、データを初期化します。
094         * これは、カラムなどヘッダー系の情報は、元と同じオブジェクトを共有し、
095         * データ部のみ空にした DBTableModel を作成することを意味します。
096         * この際、consistencyKey も複写しますので、整合性は崩れないように、
097         * データ登録を行う必要があります。
098         *
099         * @og.rev 4.0.0.0 (2007/06/28) 新規作成
100         *
101         * @return  DBTableModelオブジェクト
102         */
103        public DBTableModel newModel() {
104                DBTableModelImpl table = new DBTableModelImpl();
105
106                table.data                              = new ArrayList<String[]>( HybsSystem.BUFFER_MIDDLE );
107                table.rowHeader                 = new ArrayList<DBRowHeader>( HybsSystem.BUFFER_MIDDLE );
108                table.names                             = names;
109                table.dbColumns                 = dbColumns;
110                table.numberOfColumns   = numberOfColumns;
111                table.columnMap                 = columnMap;
112                table.lastRow                   = -1;
113                table.consistencyKey    = consistencyKey;
114
115                return table ;
116        }
117
118        /**
119         * カラム名配列を返します。
120         *
121         * @og.rev 3.0.0.0 (2002/12/25) カラム名配列を取得するメソッドを追加する。
122         * @og.rev 3.5.6.0 (2004/06/18) 配列をそのまま返さずに、clone して返します。
123         * @og.rev 3.6.0.0 (2004/09/22) names が null の場合は、初期設定エラーとします。
124         *
125         * @return      カラム名配列
126         */
127        public String[] getNames() {
128                if( names != null ) {
129                        return names.clone();
130                }
131
132                String errMsg = "カラム名配列が、初期化されていません。";
133                throw new HybsSystemException( errMsg );
134        }
135
136        //////////////////////////////////////////////////////////////////////////
137        //
138        //   DBTableModelImpl 独自の実装部分
139        //
140        //////////////////////////////////////////////////////////////////////////
141
142        /**
143         * column に対応した 値を登録します。
144         * column には、番号ではなく、ラベルを指定します。
145         * 指定の行番号が、内部のデータ件数より多い場合は、データを追加します。
146         *
147         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
148         *
149         * @param   aRow    値が変更される行
150         * @param   columnName    値が変更されるカラム名
151         * @param   value   新しい値。null も可
152         */
153        public void setValue( final int aRow, final String columnName, final String value ) {
154                int aColumn = getColumnNo( columnName );
155                int size = getRowCount();
156                if( size > aRow ) {
157                        setRowHeader( aRow,UPDATE_TYPE );
158                        setValueAt( value , aRow, aColumn );
159                }
160                else {
161                        for( int i = 0; i< (aRow-size)+1; i++ ) {
162                                String[] columnValues = new String[ numberOfColumns ];
163                                for(int j = 0; j < numberOfColumns; j++) {              // 3.5.5.7 (2004/05/10)
164                                        columnValues[j] = "";
165                                }
166                                addColumnValues( columnValues );
167                        }
168                        setValueAt( value , aRow, aColumn );
169                }
170        }
171
172        /**
173         * 行を削除します。
174         * 物理削除ではなく、論理削除です。
175         * データを取り込むことは可能です。
176         *
177         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
178         *
179         * @param   aRow    論理削除される行
180         */
181        public void rowDelete( final int aRow ) {
182                setRowHeader( aRow,DELETE_TYPE );
183        }
184
185        /**
186         * row にあるセルのオブジェクト値を置き換えて、行を削除します。
187         * 物理削除ではなく、論理削除です。
188         * 値を置き換えたデータを取り込むことが可能です。
189         *
190         * @og.rev 3.5.4.2 (2003/12/15) 新規追加
191         *
192         * @param   values  新しい配列値。
193         * @param   aRow    論理削除される行
194         *
195         */
196        public void rowDelete( final String[] values, final int aRow ) {
197                if( numberOfColumns == values.length ) {                // 3.5.5.7 (2004/05/10)
198                        setRowHeader( aRow,DELETE_TYPE );
199                        data.set( aRow,values );
200                        lastRow = -1;                           // 3.5.5.7 (2004/05/10)
201                }
202                else {
203                        String errMsg = "カラム名の個数が不一致です。 [" + numberOfColumns + "] : [" + values.length + "]"
204                                                                + " values=" + StringUtil.array2csv( values ) ;         // 5.1.8.0 (2010/07/01) errMsg 修正
205                        throw new HybsSystemException( errMsg );
206                }
207        }
208
209        /**
210         * 行を物理削除します。
211         * メモリ上で編集する場合に使用しますが,一般アプリケーションからの
212         * 使用は、物理削除の為,お勧めいたしません。
213         *
214         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
215         *
216         * @param   aRow    物理削除される行
217         *
218         */
219        public void removeValue( final int aRow ) {
220                data.remove( aRow );
221                rowHeader.remove( aRow );
222                lastRow = -1;                           // 3.5.5.7 (2004/05/10)
223        }
224
225        //////////////////////////////////////////////////////////////////////////
226        //
227        //   DBTableModel インターフェースの実装部分
228        //
229        //////////////////////////////////////////////////////////////////////////
230
231        /**
232         * カラムのラベル名を返します。
233         * カラムの項目名に対して,見える形の文字列を返します。
234         * 一般には,リソースバンドルと組合せて,各国ロケール毎にラベルを
235         * 切替えます。
236         *
237         * @param   column カラム番号
238         *
239         * @return  カラムのラベル名
240         */
241        public String getColumnLabel( final int column ) {
242                return dbColumns[column].getLabel();
243        }
244
245        /**
246         * row および column にあるセルの属性値をStringに変換して返します。
247         *
248         * @og.rev 3.5.5.7 (2004/05/10) 連続同一 row アクセスのキャッシュ利用対応
249         *
250         * @param   aRow     値が参照される行
251         * @param   aColumn  値が参照される列
252         *
253         * @return  指定されたセルの値 String
254         */
255        public String getValue( final int aRow, final int aColumn ) {
256                if( aRow != lastRow ) {
257                        lastData = data.get(aRow);
258                        lastRow = aRow ;
259                }
260                return lastData[aColumn] ;
261        }
262
263        /**
264         * row および columnName にあるセルの属性値をStringに変換して返します。
265         *
266         * @param   aRow       値が参照される行
267         * @param   columnName 値が参照されるカラム名
268         *
269         * @return  指定されたセルの値 String
270         * @see #getValue( int , int )
271         */
272        public String getValue( final int aRow, final String columnName ) {
273                return getValue( aRow,getColumnNo( columnName ) );
274        }
275
276        /**
277         * カラム(列)にカラムオブジェクトを割り当てます。
278         * カラムオブジェクトは,ラベルやネームなど,そのカラム情報を
279         * 保持したオブジェクトです。
280         *
281         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
282         *
283         * @param   clm        ヘッダーを適応するカラム(列)
284         * @param   dbColumn   カラムオブジェクト
285         */
286        public void setDBColumn( final int clm, final DBColumn dbColumn ) {
287                dbColumns[clm] = dbColumn;
288                names[clm]     = dbColumn.getName();
289                columnMap.put( names[clm].toUpperCase(Locale.JAPAN),Integer.valueOf( clm ) );
290        }
291
292        /**
293         * カラム(列)のカラムオブジェクトを返します。
294         * カラムオブジェクトは,ラベルやネームなど,そのカラム情報を
295         * 保持したオブジェクトです。
296         *
297         * @param       clm     ヘッダーを適応するカラム(列)
298         *
299         * @return      カラムオブジェクト
300         */
301        public DBColumn getDBColumn( final int clm ) {
302                return dbColumns[ clm ];
303        }
304
305        /**
306         * カラムオブジェクト配列を返します。
307         * カラムオブジェクトは,ラベルやネームなど,そのカラム情報を
308         * 保持したオブジェクトです。
309         *
310         * @og.rev 4.0.0.0 (2005/12/31) 新規追加
311         *
312         * @return      カラムオブジェクト配列
313         */
314        public DBColumn[] getDBColumns() {
315                int size = dbColumns.length;
316                DBColumn[] clms = new DBColumn[size];
317                System.arraycopy( dbColumns,0,clms,0,size );
318                return clms;
319        }
320
321        /**
322         * カラム名をもとに、そのカラム番号を返します。
323         * カラム名が存在しない場合は、 HybsSystemException を throw します。
324         *
325         * @param   columnName   カラム名
326         *
327         * @return  カラム番号
328         * @see #getColumnNo( String ,boolean )
329         */
330        public int getColumnNo( final String columnName ) {
331                return getColumnNo( columnName,true );
332        }
333
334        /**
335         * カラム名をもとに、そのカラム番号を返します。
336         * useThrow が、true の場合は、カラム名が存在しない場合は、 HybsSystemException を
337         * throw します。useThrow が、false の場合は、カラム名が存在しない場合は、 -1 を返します。
338         *
339         * @og.rev 4.0.0.0 (2005/12/31) 新規追加
340         *
341         * @param   columnName   カラム名
342         * @param   useThrow     カラム名が存在しない場合に、Exception を throw するかどうか
343         *
344         * @return  カラム番号
345         * @see #getColumnNo( String )
346         */
347        public int getColumnNo( final String columnName,final boolean useThrow ) {
348                if( columnName != null ) {
349                        Integer no = columnMap.get( columnName.toUpperCase(Locale.JAPAN) );
350                        if( no != null ) { return no.intValue() ; }
351                }
352
353                if( useThrow ) {
354                        String errMsg = "カラム名が存在しません:[" + columnName + "]" ;
355                        throw new HybsSystemException( errMsg );
356                }
357                else {
358                        return -1;
359                }
360        }
361
362        //////////////////////////////////////////////////////////////////////////
363        //
364        //   DBTableModel クラスのオーバーライド部分
365        //
366        //////////////////////////////////////////////////////////////////////////
367
368        /**
369         * row の下に属性値配列を追加登録します。
370         *
371         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
372         *
373         * @param   values  属性値配列
374         * @param   aRow    値が参照される行
375         *
376         */
377        public void addValues( final String[] values ,final int aRow ) {
378                addValues( values, aRow, true ); // 4.3.1.0 (2008/09/04)
379        }
380
381        /**
382         * row の下に属性値配列を追加登録します。
383         * isWritableをfalseにした場合、編集不可能な状態で追加されます。
384         *
385         * @og.rev 4.3.1.0 (2008/09/04) interface に新規登録
386         *
387         * @param   values  属性値配列
388         * @param   aRow    値が参照される行
389         * @param   isWritable 編集不可能な状態で追加するか
390         *
391         */
392        public void addValues( final String[] values ,final int aRow, final boolean isWritable ) {
393                data.add( aRow,values );
394                lastRow = -1;                           // 3.5.5.7 (2004/05/10)
395
396                DBRowHeader rowhed = new DBRowHeader();
397                if( isWritable ) {
398                        rowhed.setType( INSERT_TYPE );
399                }
400                else {
401                        rowhed.setWritable( false );
402                        rowhed.setChecked( false );
403                }
404                rowHeader.add( aRow,rowhed );
405        }
406
407        /**
408         * row あるセルの属性値配列を追加登録します。
409         * これは,初期登録時のみに使用します。
410         *
411         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
412         *
413         * @param   values  属性値配列
414         *
415         */
416        public void addColumnValues( final String[] values ) {
417                data.add( values );
418                lastRow = -1;                           // 3.5.5.7 (2004/05/10)
419                rowHeader.add( new DBRowHeader() );
420        }
421
422        //////////////////////////////////////////////////////////////////////////
423        //
424        //             Implementation of the TableModel Interface
425        //
426        //////////////////////////////////////////////////////////////////////////
427
428        // MetaData
429
430        /**
431         * カラム名を取得します。
432         *
433         * @param   column  最初のカラムは 0、2番目のカラムは 1、などとする。
434         *
435         * @return  カラム名
436         *
437         */
438        public String getColumnName( final int column ) {
439                return names[column];
440        }
441
442        /**
443         * データテーブル内の列の数を返します。
444         *
445         * @return  モデルの列数
446         *
447         */
448        public int getColumnCount() {
449                return numberOfColumns ;
450        }
451
452        /**
453         * データテーブル内の行の数を返します。
454         *
455         * @return  モデルの行数
456         *
457         */
458        public int getRowCount() {
459                return data.size() ;
460        }
461
462        /**
463         * column および row にあるセルのオブジェクト値を設定します。
464         * このメソッドは、行番号の範囲チェックや、列番号のチェックを行いません。
465         * また、登録に際して、更新マーカー(UPDATE_TYPE等)を設定しません。
466         *
467         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
468         * @og.rev 3.5.3.1 (2003/10/31) インターフェースの見直しにより、private 化する。
469         * @og.rev 4.0.0.0 (2007/05/24) インターフェースの見直しにより、public 化する。
470         *
471         * @param   value   新しい値。null も可
472         * @param   aRow    値が変更される行
473         * @param   aColumn 値が変更される列
474         */
475        public void setValueAt( final String value, final int aRow, final int aColumn ) {
476                String[] row = data.get(aRow);
477                row[ aColumn ] = value;
478                data.set( aRow,row );
479                lastRow = -1;                           // 3.5.5.7 (2004/05/10)
480        }
481
482        //////////////////////////////////////////////////////////////////////////
483        //
484        //             DBTableModel 独自追加分
485        //
486        //////////////////////////////////////////////////////////////////////////
487
488        /**
489         * row にあるセルの属性値を配列で返します。
490         *
491         * @param   aRow     値が参照される行
492         *
493         * @return  指定されたセルの属性値
494         *
495         */
496        public String[] getValues( final int aRow ) {
497                return data.get(aRow);
498        }
499
500        /**
501         * row にあるセルのオブジェクト値を置き換えます。
502         *
503         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
504         *
505         * @param   values  新しい配列値。
506         * @param   aRow    値が変更される行
507         *
508         */
509        public void setValues( final String[] values, final int aRow ) {
510                if( numberOfColumns == values.length ) {                // 3.5.5.7 (2004/05/10)
511                        setRowHeader( aRow,UPDATE_TYPE );
512                        data.set( aRow,values );
513                        lastRow = -1;                           // 3.5.5.7 (2004/05/10)
514                }
515                else {
516                        String errMsg = "カラム名の個数が不一致です。 [" + numberOfColumns + "] : [" + values.length + "]"
517                                                                + " values=" + StringUtil.array2csv( values ) ;         // 5.1.8.0 (2010/07/01) errMsg 修正
518                        throw new HybsSystemException( errMsg );
519                }
520        }
521
522        /**
523         * 変更済みフラグを元に戻します。
524         *
525         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
526         *
527         * 一般には,データベースにテーブルモデルを登録するタイミングで、
528         * 変更済みフラグを元に戻します。
529         *
530         */
531        public void resetModify() {
532                int size = rowHeader.size() ;
533                DBRowHeader row ;
534                for( int i=0; i<size; i++ ) {
535                        row = rowHeader.get( i );
536                        row.clear();
537                }
538        }
539
540        /**
541         * 変更済みフラグを元に戻します。
542         *
543         * 一般には,データベースにテーブルモデルを登録するタイミングで、
544         * 変更済みフラグを元に戻します。
545         *
546         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
547         *
548         * @param   aRow     値が参照される行
549         */
550        public void resetModify( final int aRow ) {
551                DBRowHeader row = rowHeader.get( aRow );
552                row.clear();
553        }
554
555        /**
556         * row 単位に変更されたタイプ(追加/変更/削除)を返します。
557         * タイプは始めに一度登録するとそれ以降に変更はかかりません。
558         * つまり、始めに 追加で作成したデータは、その後変更があっても追加のままです。
559         * なにも変更されていない場合は, ""(ゼロストリング)を返します。
560         *
561         * @param   aRow     値が参照される行
562         *
563         * @return  変更されたタイプの値 String
564         *
565         */
566        public String getModifyType( final int aRow ) {
567                DBRowHeader row = rowHeader.get( aRow );
568                return row.getType();
569        }
570
571        /**
572         * row 単位に変更タイプ(追加/変更/削除)をセットします。
573         * このメソッドでは、データのバックアップは取りません。
574         * タイプは始めに一度登録するとそれ以降に変更はかかりません。
575         * なにも変更されていない場合は, ""(ゼロストリング)の状態です。
576         *
577         * @param   aRow     値が参照される行
578         * @param   modType  変更タイプ(追加/変更/削除)
579         *
580         */
581        public void setModifyType( final int aRow,final String modType ) {
582                DBRowHeader rowhed = rowHeader.get( aRow );
583                rowhed.setType( modType );
584        }
585
586        /**
587         * row 単位に変更タイプ(追加/変更/削除)をセットします。
588         * セットすると同時に、データのバックアップを取ります。
589         * タイプは始めに一度登録するとそれ以降に変更はかかりません。
590         * つまり、始めに 追加で作成したデータは、その後変更があっても追加のままです。
591         * なにも変更されていない場合は, ""(ゼロストリング)の状態です。
592         *
593         * @og.rev 3.5.6.0 (2004/06/18) setBackupData 側で 配列をコピーしているため、こちらでは不要。
594         * @og.rev 3.5.6.4 (2004/07/16) protected 化します。
595         *
596         * @param   aRow     値が参照される行
597         * @param   modType  変更タイプ(追加/変更/削除)
598         */
599        protected void setRowHeader( final int aRow,final String modType ) {
600                DBRowHeader rowhed = rowHeader.get( aRow );
601
602                rowhed.setBackupData( data.get(aRow) );
603                rowhed.setType( modType );
604        }
605
606        /**
607         * 変更データを初期値(元の取り込んだ状態)に戻します。
608         *
609         * 変更タイプ(追加/変更/削除)に応じて、処理されます。
610         * 追加時は、追加された行を削除します。
611         * 変更時は、変更された行を元に戻します。
612         * 削除時は、削除フラグを解除します。
613         * それ以外の場合(変更されていない場合)は、なにもしません。
614         *
615         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
616         * @og.rev 3.5.4.2 (2003/12/15) "DELETE" 時に値を置き換えた場合にUPDATEと同様に戻します。
617         *
618         * @param   aRow    処理を戻す(取り消す)行
619         */
620        public void resetRow( final int aRow ) {
621                String modType = getModifyType(aRow) ;
622
623                if( modType.equals( INSERT_TYPE ) ) {
624                        data.remove( aRow );
625                        rowHeader.remove( aRow );
626                }
627                else if( modType.equals( UPDATE_TYPE ) ||
628                                 modType.equals( DELETE_TYPE ) ) {
629                        DBRowHeader row = rowHeader.get( aRow );
630                        String[] obj = row.getBackupData();
631                        if( obj != null ) { data.set( aRow,obj ); }
632                        row.clear();
633                }
634                lastRow = -1;                           // 3.5.5.7 (2004/05/10)
635        }
636
637        /**
638         * 書込み許可を返します。
639         *
640         * @param   aRow     値が参照される行
641         *
642         * @return  書込み可能(true)/不可能(false)
643         */
644        public boolean isRowWritable( final int aRow ) {
645                DBRowHeader row = rowHeader.get( aRow );
646                return row.isWritable();
647        }
648
649        /**
650         * 行が書き込み可能かどうかをセットします。
651         * デフォルト/およびなにも設定しない場合は, DEFAULT_WRITABLE が
652         * 与えられています。
653         * これが true の場合は,書込み許可です。(チェックボックスを表示)
654         * false の場合は,書込み不許可(チェックボックスは表示されません。)
655         *
656         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
657         *
658         * @param   aRow     値が参照される行
659         * @param   rw 書込み可能(true)/不可能(false)
660         */
661        public void setRowWritable( final int aRow ,final boolean rw ) {
662                DBRowHeader row = rowHeader.get( aRow );
663                row.setWritable( rw );
664        }
665
666        /**
667         * 書き込み可能な行(rowWritable == true)のチェックボックスに対して
668         * 初期値を 選択済みか、非選択済みかを返します。
669         *
670         * @param   aRow      値が参照される行
671         *
672         * @return      初期値チェックON(true)/チェックOFF(false)
673         */
674        public boolean isRowChecked( final int aRow ) {
675                DBRowHeader row = rowHeader.get( aRow );
676                return row.isChecked();
677        }
678
679        /**
680         * 書き込み可能な行(rowWritable == true)のチェックボックスに対して
681         * 初期値を 選択済みにするか、非選択済みにするかを指定します。
682         *
683         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
684         *
685         * @param   aRow      値が参照される行
686         * @param   rw チェックON(true)/チェックOFF(false)
687         */
688        public void setRowChecked( final int aRow ,final boolean rw ) {
689                DBRowHeader row = rowHeader.get( aRow );
690                row.setChecked( rw );
691        }
692
693        /**
694         * 行指定の書込み許可を与えます。
695         * 具体的には,チェックボックスの表示/非表示を指定します。
696         * これが true の場合は,書込み許可です。(チェックボックスを表示)
697         * false の場合は,書込み不許可(チェックボックスは表示されません。)
698         * 行毎に書込み許可/不許可を指定する場合は,1カラム目に writable
699         * カラムを用意して true/false を指定します。
700         * この writable カラムとの論理積により最終的にチェックボックスの
701         * 表示の ON/OFF が決まります。
702         * なにも設定しない場合は, ViewForm.DEFAULT_WRITABLE が設定されます。
703         *
704         * @param   rw 書込み可能(true)/不可能(false)
705         */
706        public void setDefaultRowWritable( final boolean rw ) {
707                int size = rowHeader.size() ;
708                DBRowHeader row ;
709                for( int i=0; i<size; i++ ) {
710                        row = rowHeader.get( i );
711                        row.setWritable( rw );
712                }
713        }
714
715        /**
716         * 書き込み可能な行(rowWritable == true)のチェックボックスに対して
717         * 初期値を 選択済みにするか、非選択済みにするかを指定します。
718         *
719         * @param   rw 選択状態(true)/非選択状態(false)
720         */
721        public void setDefaultRowChecked( final boolean rw ) {
722                int size = rowHeader.size() ;
723                DBRowHeader row ;
724                for( int i=0; i<size; i++ ) {
725                        row = rowHeader.get( i );
726                        row.setChecked( rw );
727                }
728        }
729
730        /**
731         * 検索結果が オーバーフローしたかどうかをチェックします。
732         * Query で検索した場合に、DB_MAX_ROW_COUNT または、Query.setMaxRowCount( int maxRowCount )
733         * で指定された値よりも検索結果が多い場合に、DBTableModel は、先の設定値までの
734         * データを取り込みます。そのときに、オーバーフローフラグを立てておくことで、最大件数を
735         * オーバーしたかどうかを判断します。
736         *
737         * @return   オーバーフロー(true)/正常(false)
738         */
739        public boolean isOverflow() {
740                return overflow;
741        }
742
743        /**
744         * 検索結果が オーバーフローしたかどうかを設定します。
745         * Query で検索した場合に、DB_MAX_ROW_COUNT または、Query.setMaxRowCount( int maxRowCount )
746         * で指定された値よりも検索結果が多い場合に、DBTableModel は、先の設定値までの
747         * データを取り込みます。そのときに、オーバーフローフラグを立てておくことで、最大件数を
748         * オーバーしたかどうかを判断します。
749         *
750         * @param   of オーバーフロー(true)/正常(false)
751         */
752        public void setOverflow( final boolean of ) {
753                overflow = of;
754        }
755
756        /**
757         * 検索されたDBTableModelが登録時に同一かどうかを判断する為の 整合性キーを取得します。
758         *
759         * ここでの整合性は、同一セッション(ユーザー)毎にユニークかどうかで対応します。
760         * 分散環境(複数のセッション間)での整合性は、確保できません。
761         * 整合性キー は、オブジェクト作成時刻としますが、将来変更される可能性があります。
762         *
763         * @og.rev 3.5.5.5 (2004/04/23) 新規追加
764         *
765         * @return   整合性キー(オブジェクトの作成時刻)
766         */
767        public String getConsistencyKey() {
768                return consistencyKey;
769        }
770
771        /**
772         * カラムに定義されたDBTypeよりNativeタイプを返します。
773         * Nativeタイプはorg.opengion.fukurou.model.NativeTypeで定義されています。
774         *
775         * @og.rev 4.1.1.2 (2008/02/28) 新規追加
776         *
777         * @param  clm      値が参照される列
778         *
779         * @return Nativeタイプ
780         * @see org.opengion.fukurou.model.NativeType
781         */
782        public NativeType getNativeType( final int clm ) {
783                return dbColumns[clm].getNativeType();
784        }
785
786        /**
787         * カラム(列)にmustタイプ値を割り当てます。
788         * この値は、columnCheck 時の nullCheck や mustAnyCheck の
789         * チェック対象カラムとして認識されます。
790         *
791         * @og.rev 4.1.2.1 (2008/03/13) interface に新規登録
792         *
793         * @param   dbColumn  カラムオブジェクト
794         * @param   type      mustタイプ(must,mustAny)
795         */
796        public void addMustType( final int dbColumn, final String type ) {
797                Set<String> set = mustMap.get( type );
798                if( set == null ) { set = new HashSet<String>(); }
799                set.add( names[dbColumn] );
800                mustMap.put( type,set );
801        }
802
803        /**
804         * mustType="must"時のカラム名を、文字列配列として返します。
805         * この値は、columnCheck 時の nullCheck のチェック対象カラムとして
806         * 認識されます。
807         * カラム名配列は、ソート済みです。
808         *
809         * @og.rev 4.1.2.1 (2008/03/13) interface に新規登録
810         *
811         * @return  mustType="must"時のカラム名配列(ソート済み)
812         */
813        public String[] getMustArray() {
814                String[] rtn = null;
815
816                Set<String> set = mustMap.get( "must" );
817                if( set != null && ! set.isEmpty() ) {
818                        rtn = set.toArray( new String[set.size()] );
819                        Arrays.sort( rtn );
820                }
821                return rtn ;
822        }
823
824        /**
825         * mustType="mustAny" 他のカラム名を、文字列配列として返します。
826         * この値は、columnCheck 時の mustAnyCheck のチェック対象カラムとして
827         * 認識されます。
828         * カラム名配列は、ソート済みです。
829         *
830         * @og.rev 4.1.2.1 (2008/03/13) interface に新規登録
831         *
832         * @return  mustType="mustAny"時のカラム名配列(ソート済み)
833         */
834        public String[] getMustAnyArray() {
835
836                List<String> list = new ArrayList<String>();
837
838                String[] keys = mustMap.keySet().toArray( new String[mustMap.size()] );
839                for( int i=0; i<keys.length; i++ ) {
840                        String key = keys[i];
841                        if( ! "must".equals( key ) ) {
842                                Set<String> set = mustMap.get( key );
843                                if( set != null && !set.isEmpty() ) {
844                                        String str = StringUtil.iterator2line( set.iterator(),"|" );
845                                        list.add( str );
846                                }
847                        }
848                }
849
850                String[] rtn = null;
851                if( ! list.isEmpty() ) {
852                        rtn = list.toArray( new String[list.size()] );
853                        Arrays.sort( rtn );
854                }
855
856                return rtn ;
857        }
858}