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