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//              data.add( aRow,values );
379//              lastRow = -1;                           // 3.5.5.7 (2004/05/10)
380//
381//              DBRowHeader rowhed = new DBRowHeader();
382//              rowhed.setType( INSERT_TYPE );
383//              rowHeader.add( aRow,rowhed );
384                addValues( values, aRow, true ); // 4.3.1.0 (2008/09/04)
385        }
386
387        /**
388         * row の下に属性値配列を追加登録します。
389         * isWritableをfalseにした場合、編集不可能な状態で追加されます。
390         *
391         * @og.rev 4.3.1.0 (2008/09/04) interface に新規登録
392         *
393         * @param   values  属性値配列
394         * @param   aRow    値が参照される行
395         * @param   isWritable 編集不可能な状態で追加するか
396         *
397         */
398        public void addValues( final String[] values ,final int aRow, final boolean isWritable ) {
399                data.add( aRow,values );
400                lastRow = -1;                           // 3.5.5.7 (2004/05/10)
401
402                DBRowHeader rowhed = new DBRowHeader();
403                if( isWritable ) {
404                        rowhed.setType( INSERT_TYPE );
405                }
406                else {
407                        rowhed.setWritable( false );
408                        rowhed.setChecked( false );
409                }
410                rowHeader.add( aRow,rowhed );
411        }
412
413        /**
414         * row あるセルの属性値配列を追加登録します。
415         * これは,初期登録時のみに使用します。
416         *
417         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
418         *
419         * @param   values  属性値配列
420         *
421         */
422        public void addColumnValues( final String[] values ) {
423                data.add( values );
424                lastRow = -1;                           // 3.5.5.7 (2004/05/10)
425                rowHeader.add( new DBRowHeader() );
426        }
427
428        //////////////////////////////////////////////////////////////////////////
429        //
430        //             Implementation of the TableModel Interface
431        //
432        //////////////////////////////////////////////////////////////////////////
433
434        // MetaData
435
436        /**
437         * カラム名を取得します。
438         *
439         * @param   column  最初のカラムは 0、2番目のカラムは 1、などとする。
440         *
441         * @return  カラム名
442         *
443         */
444        public String getColumnName( final int column ) {
445                return names[column];
446        }
447
448        /**
449         * データテーブル内の列の数を返します。
450         *
451         * @return  モデルの列数
452         *
453         */
454        public int getColumnCount() {
455                return numberOfColumns ;
456        }
457
458        /**
459         * データテーブル内の行の数を返します。
460         *
461         * @return  モデルの行数
462         *
463         */
464        public int getRowCount() {
465                return data.size() ;
466        }
467
468        /**
469         * column および row にあるセルのオブジェクト値を設定します。
470         * このメソッドは、行番号の範囲チェックや、列番号のチェックを行いません。
471         * また、登録に際して、更新マーカー(UPDATE_TYPE等)を設定しません。
472         *
473         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
474         * @og.rev 3.5.3.1 (2003/10/31) インターフェースの見直しにより、private 化する。
475         * @og.rev 4.0.0.0 (2007/05/24) インターフェースの見直しにより、public 化する。
476         *
477         * @param   value   新しい値。null も可
478         * @param   aRow    値が変更される行
479         * @param   aColumn 値が変更される列
480         */
481        public void setValueAt( final String value, final int aRow, final int aColumn ) {
482//              setRowHeader( aRow,UPDATE_TYPE );
483                String[] row = data.get(aRow);
484                row[ aColumn ] = value;
485                data.set( aRow,row );
486                lastRow = -1;                           // 3.5.5.7 (2004/05/10)
487        }
488
489        //////////////////////////////////////////////////////////////////////////
490        //
491        //             DBTableModel 独自追加分
492        //
493        //////////////////////////////////////////////////////////////////////////
494
495        /**
496         * row にあるセルの属性値を配列で返します。
497         *
498         * @param   aRow     値が参照される行
499         *
500         * @return  指定されたセルの属性値
501         *
502         */
503        public String[] getValues( final int aRow ) {
504                return data.get(aRow);
505        }
506
507        /**
508         * row にあるセルのオブジェクト値を置き換えます。
509         *
510         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
511         *
512         * @param   values  新しい配列値。
513         * @param   aRow    値が変更される行
514         *
515         */
516        public void setValues( final String[] values, final int aRow ) {
517                if( numberOfColumns == values.length ) {                // 3.5.5.7 (2004/05/10)
518                        setRowHeader( aRow,UPDATE_TYPE );
519                        data.set( aRow,values );
520                        lastRow = -1;                           // 3.5.5.7 (2004/05/10)
521                }
522                else {
523                        String errMsg = "カラム名の個数が不一致です。 [" + numberOfColumns + "] : [" + values.length + "]"
524                                                                + " values=" + StringUtil.array2csv( values ) ;         // 5.1.8.0 (2010/07/01) errMsg 修正
525                        throw new HybsSystemException( errMsg );
526                }
527        }
528
529        /**
530         * 変更済みフラグを元に戻します。
531         *
532         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
533         *
534         * 一般には,データベースにテーブルモデルを登録するタイミングで、
535         * 変更済みフラグを元に戻します。
536         *
537         */
538        public void resetModify() {
539                int size = rowHeader.size() ;
540                DBRowHeader row ;
541                for( int i=0; i<size; i++ ) {
542                        row = rowHeader.get( i );
543                        row.clear();
544                }
545        }
546
547        /**
548         * 変更済みフラグを元に戻します。
549         *
550         * 一般には,データベースにテーブルモデルを登録するタイミングで、
551         * 変更済みフラグを元に戻します。
552         *
553         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
554         *
555         * @param   aRow     値が参照される行
556         */
557        public void resetModify( final int aRow ) {
558                DBRowHeader row = rowHeader.get( aRow );
559                row.clear();
560        }
561
562        /**
563         * row 単位に変更されたタイプ(追加/変更/削除)を返します。
564         * タイプは始めに一度登録するとそれ以降に変更はかかりません。
565         * つまり、始めに 追加で作成したデータは、その後変更があっても追加のままです。
566         * なにも変更されていない場合は, ""(ゼロストリング)を返します。
567         *
568         * @param   aRow     値が参照される行
569         *
570         * @return  変更されたタイプの値 String
571         *
572         */
573        public String getModifyType( final int aRow ) {
574                DBRowHeader row = rowHeader.get( aRow );
575                return row.getType();
576        }
577
578        /**
579         * row 単位に変更タイプ(追加/変更/削除)をセットします。
580         * このメソッドでは、データのバックアップは取りません。
581         * タイプは始めに一度登録するとそれ以降に変更はかかりません。
582         * なにも変更されていない場合は, ""(ゼロストリング)の状態です。
583         *
584         * @param   aRow     値が参照される行
585         * @param   modType  変更タイプ(追加/変更/削除)
586         *
587         */
588        public void setModifyType( final int aRow,final String modType ) {
589                DBRowHeader rowhed = rowHeader.get( aRow );
590                rowhed.setType( modType );
591        }
592
593        /**
594         * row 単位に変更タイプ(追加/変更/削除)をセットします。
595         * セットすると同時に、データのバックアップを取ります。
596         * タイプは始めに一度登録するとそれ以降に変更はかかりません。
597         * つまり、始めに 追加で作成したデータは、その後変更があっても追加のままです。
598         * なにも変更されていない場合は, ""(ゼロストリング)の状態です。
599         *
600         * @og.rev 3.5.6.0 (2004/06/18) setBackupData 側で 配列をコピーしているため、こちらでは不要。
601         * @og.rev 3.5.6.4 (2004/07/16) protected 化します。
602         *
603         * @param   aRow     値が参照される行
604         * @param   modType  変更タイプ(追加/変更/削除)
605         */
606        protected void setRowHeader( final int aRow,final String modType ) {
607                DBRowHeader rowhed = rowHeader.get( aRow );
608
609                rowhed.setBackupData( data.get(aRow) );
610                rowhed.setType( modType );
611        }
612
613        /**
614         * 変更データを初期値(元の取り込んだ状態)に戻します。
615         *
616         * 変更タイプ(追加/変更/削除)に応じて、処理されます。
617         * 追加時は、追加された行を削除します。
618         * 変更時は、変更された行を元に戻します。
619         * 削除時は、削除フラグを解除します。
620         * それ以外の場合(変更されていない場合)は、なにもしません。
621         *
622         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
623         * @og.rev 3.5.4.2 (2003/12/15) "DELETE" 時に値を置き換えた場合にUPDATEと同様に戻します。
624         *
625         * @param   aRow    処理を戻す(取り消す)行
626         */
627        public void resetRow( final int aRow ) {
628                String modType = getModifyType(aRow) ;
629
630                if( modType.equals( INSERT_TYPE ) ) {
631                        data.remove( aRow );
632                        rowHeader.remove( aRow );
633                }
634                else if( modType.equals( UPDATE_TYPE ) ||
635                                 modType.equals( DELETE_TYPE ) ) {
636                        DBRowHeader row = rowHeader.get( aRow );
637                        String[] obj = row.getBackupData();
638                        if( obj != null ) { data.set( aRow,obj ); }
639                        row.clear();
640                }
641                lastRow = -1;                           // 3.5.5.7 (2004/05/10)
642        }
643
644        /**
645         * 書込み許可を返します。
646         *
647         * @param   aRow     値が参照される行
648         *
649         * @return  書込み可能(true)/不可能(false)
650         */
651        public boolean isRowWritable( final int aRow ) {
652                DBRowHeader row = rowHeader.get( aRow );
653                return row.isWritable();
654        }
655
656        /**
657         * 行が書き込み可能かどうかをセットします。
658         * デフォルト/およびなにも設定しない場合は, DEFAULT_WRITABLE が
659         * 与えられています。
660         * これが true の場合は,書込み許可です。(チェックボックスを表示)
661         * false の場合は,書込み不許可(チェックボックスは表示されません。)
662         *
663         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
664         *
665         * @param   aRow     値が参照される行
666         * @param   rw 書込み可能(true)/不可能(false)
667         */
668        public void setRowWritable( final int aRow ,final boolean rw ) {
669                DBRowHeader row = rowHeader.get( aRow );
670                row.setWritable( rw );
671        }
672
673        /**
674         * 書き込み可能な行(rowWritable == true)のチェックボックスに対して
675         * 初期値を 選択済みか、非選択済みかを返します。
676         *
677         * @param   aRow      値が参照される行
678         *
679         * @return      初期値チェックON(true)/チェックOFF(false)
680         */
681        public boolean isRowChecked( final int aRow ) {
682                DBRowHeader row = rowHeader.get( aRow );
683                return row.isChecked();
684        }
685
686        /**
687         * 書き込み可能な行(rowWritable == true)のチェックボックスに対して
688         * 初期値を 選択済みにするか、非選択済みにするかを指定します。
689         *
690         * @og.rev 3.1.0.0 (2003/03/20) 同期メソッド(synchronized付き)を非同期に変更する。
691         *
692         * @param   aRow      値が参照される行
693         * @param   rw チェックON(true)/チェックOFF(false)
694         */
695        public void setRowChecked( final int aRow ,final boolean rw ) {
696                DBRowHeader row = rowHeader.get( aRow );
697                row.setChecked( rw );
698        }
699
700        /**
701         * 行指定の書込み許可を与えます。
702         * 具体的には,チェックボックスの表示/非表示を指定します。
703         * これが true の場合は,書込み許可です。(チェックボックスを表示)
704         * false の場合は,書込み不許可(チェックボックスは表示されません。)
705         * 行毎に書込み許可/不許可を指定する場合は,1カラム目に writable
706         * カラムを用意して true/false を指定します。
707         * この writable カラムとの論理積により最終的にチェックボックスの
708         * 表示の ON/OFF が決まります。
709         * なにも設定しない場合は, ViewForm.DEFAULT_WRITABLE が設定されます。
710         *
711         * @param   rw 書込み可能(true)/不可能(false)
712         */
713        public void setDefaultRowWritable( final boolean rw ) {
714                int size = rowHeader.size() ;
715                DBRowHeader row ;
716                for( int i=0; i<size; i++ ) {
717                        row = rowHeader.get( i );
718                        row.setWritable( rw );
719                }
720        }
721
722        /**
723         * 書き込み可能な行(rowWritable == true)のチェックボックスに対して
724         * 初期値を 選択済みにするか、非選択済みにするかを指定します。
725         *
726         * @param   rw 選択状態(true)/非選択状態(false)
727         */
728        public void setDefaultRowChecked( final boolean rw ) {
729                int size = rowHeader.size() ;
730                DBRowHeader row ;
731                for( int i=0; i<size; i++ ) {
732                        row = rowHeader.get( i );
733                        row.setChecked( rw );
734                }
735        }
736
737        /**
738         * 検索結果が オーバーフローしたかどうかをチェックします。
739         * Query で検索した場合に、DB_MAX_ROW_COUNT または、Query.setMaxRowCount( int maxRowCount )
740         * で指定された値よりも検索結果が多い場合に、DBTableModel は、先の設定値までの
741         * データを取り込みます。そのときに、オーバーフローフラグを立てておくことで、最大件数を
742         * オーバーしたかどうかを判断します。
743         *
744         * @return   オーバーフロー(true)/正常(false)
745         */
746        public boolean isOverflow() {
747                return overflow;
748        }
749
750        /**
751         * 検索結果が オーバーフローしたかどうかを設定します。
752         * Query で検索した場合に、DB_MAX_ROW_COUNT または、Query.setMaxRowCount( int maxRowCount )
753         * で指定された値よりも検索結果が多い場合に、DBTableModel は、先の設定値までの
754         * データを取り込みます。そのときに、オーバーフローフラグを立てておくことで、最大件数を
755         * オーバーしたかどうかを判断します。
756         *
757         * @param   of オーバーフロー(true)/正常(false)
758         */
759        public void setOverflow( final boolean of ) {
760                overflow = of;
761        }
762
763        /**
764         * 検索されたDBTableModelが登録時に同一かどうかを判断する為の 整合性キーを取得します。
765         *
766         * ここでの整合性は、同一セッション(ユーザー)毎にユニークかどうかで対応します。
767         * 分散環境(複数のセッション間)での整合性は、確保できません。
768         * 整合性キー は、オブジェクト作成時刻としますが、将来変更される可能性があります。
769         *
770         * @og.rev 3.5.5.5 (2004/04/23) 新規追加
771         *
772         * @return   整合性キー(オブジェクトの作成時刻)
773         */
774        public String getConsistencyKey() {
775                return consistencyKey;
776        }
777
778        /**
779         * カラムに定義されたDBTypeよりNativeタイプを返します。
780         * Nativeタイプはorg.opengion.fukurou.model.NativeTypeで定義されています。
781         *
782         * @og.rev 4.1.1.2 (2008/02/28) 新規追加
783         *
784         * @param  clm      値が参照される列
785         *
786         * @return Nativeタイプ
787         * @see org.opengion.fukurou.model.NativeType
788         */
789        public NativeType getNativeType( final int clm ) {
790                return dbColumns[clm].getNativeType();
791        }
792
793        /**
794         * カラム(列)にmustタイプ値を割り当てます。
795         * この値は、columnCheck 時の nullCheck や mustAnyCheck の
796         * チェック対象カラムとして認識されます。
797         *
798         * @og.rev 4.1.2.1 (2008/03/13) interface に新規登録
799         *
800         * @param   dbColumn  カラムオブジェクト
801         * @param   type      mustタイプ(must,mustAny)
802         */
803        public void addMustType( final int dbColumn, final String type ) {
804                Set<String> set = mustMap.get( type );
805                if( set == null ) { set = new HashSet<String>(); }
806                set.add( names[dbColumn] );
807                mustMap.put( type,set );
808        }
809
810        /**
811         * mustType="must"時のカラム名を、文字列配列として返します。
812         * この値は、columnCheck 時の nullCheck のチェック対象カラムとして
813         * 認識されます。
814         * カラム名配列は、ソート済みです。
815         *
816         * @og.rev 4.1.2.1 (2008/03/13) interface に新規登録
817         *
818         * @return  mustType="must"時のカラム名配列(ソート済み)
819         */
820        public String[] getMustArray() {
821                String[] rtn = null;
822
823                Set<String> set = mustMap.get( "must" );
824//              if( set != null && set.size() > 0 ) {
825                if( set != null && ! set.isEmpty() ) {
826                        rtn = set.toArray( new String[set.size()] );
827                        Arrays.sort( rtn );
828                }
829                return rtn ;
830        }
831
832        /**
833         * mustType="mustAny" 他のカラム名を、文字列配列として返します。
834         * この値は、columnCheck 時の mustAnyCheck のチェック対象カラムとして
835         * 認識されます。
836         * カラム名配列は、ソート済みです。
837         *
838         * @og.rev 4.1.2.1 (2008/03/13) interface に新規登録
839         *
840         * @return  mustType="mustAny"時のカラム名配列(ソート済み)
841         */
842        public String[] getMustAnyArray() {
843
844                List<String> list = new ArrayList<String>();
845
846                String[] keys = mustMap.keySet().toArray( new String[mustMap.size()] );
847                for( int i=0; i<keys.length; i++ ) {
848                        String key = keys[i];
849                        if( ! "must".equals( key ) ) {
850                                Set<String> set = mustMap.get( key );
851//                              if( set != null && set.size() > 0 ) {
852                                if( set != null && !set.isEmpty() ) {
853                                        String str = StringUtil.iterator2line( set.iterator(),"|" );
854                                        list.add( str );
855                                }
856                        }
857                }
858
859                String[] rtn = null;
860//              if( list.size() > 0 ) {
861                if( ! list.isEmpty() ) {
862                        rtn = list.toArray( new String[list.size()] );
863                        Arrays.sort( rtn );
864                }
865
866                return rtn ;
867        }
868}