    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         * 行毎に書込み許可/不許可を指定する場合は,１カラム目に 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}