    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.fukurou.process;
    017
    018import org.opengion.fukurou.system.OgRuntimeException ;         // 6.4.2.0 (2016/01/29)
    019import org.opengion.fukurou.model.DataModel;
    020import org.opengion.fukurou.model.NativeType;
    021import org.opengion.fukurou.util.StringUtil;
    022import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.1.0.0 (2014/12/26) refactoring
    023import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.1.0.0 (2014/12/26) refactoring
    024
    025import java.util.Arrays;
    026
    027/**
    028 * LineModel は、データの１行分を管理する為の TableModel と類似の実装クラスです。
    029 *
    030 * データの１行分を LineModel に割り当てます。
    031 * カラム番号は、0 から始まります。カラム名よりカラム番号を求める場合に、
    032 * 存在しない場合は、-1 を返します。
    033 * カラム番号が -1 の場合は、処理を行いません。
    034 *
    035 * 注意：このクラスは、同期処理されていません。
    036 *
    037 * @version  4.0
    038 * @author   Kazuhiko Hasegawa
    039 * @since    JDK5.0,
    040 */
    041public class LineModel implements DataModel<Object> {           // 4.3.3.6 (2008/11/15) Generics警告対応
    042        /** タブセパレータ  */
    043        private static final char TAB = '\t';           // 6.0.2.5 (2014/10/31) タブ区切り文字を char 化します。
    044
    045        private String[]        names   ;
    046        private Object[]        data    ;
    047        private int                     dtSize  ;
    048        private int                     rowNo   = -1;
    049
    050        /**
    051         * デフォルトコンストラクター
    052         *
    053         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
    054         */
    055        public LineModel() { super(); }         // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    056
    057        /**
    058         * このオブジェクトを初期化します。
    059         * 指定の引数分の内部配列を作成します。
    060         *
    061         * @param   columnCount カラム数
    062         */
    063        public void init( final int columnCount ) {
    064                if( columnCount <= 0 ) {
    065                        final String errMsg = "内部配列の数量が 0か、負です。count=[" + columnCount + "]";
    066                        throw new OgRuntimeException( errMsg );
    067                }
    068                dtSize  = columnCount;
    069                names   = new String[dtSize];
    070                data    = new Object[dtSize];
    071        }
    072
    073        /**
    074         * カラム名配列を指定して、このオブジェクトを初期化します。
    075         *
    076         * @param   clmNms カラム名配列(可変長引数)
    077         */
    078        public void init( final String... clmNms ) {
    079                if( clmNms == null || clmNms.length == 0 ) {            // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。
    080                        final String errMsg = "カラム名配列が、指定されていません。";
    081                        throw new OgRuntimeException( errMsg );
    082                }
    083                dtSize  = clmNms.length;
    084                names   = new String[dtSize];
    085                System.arraycopy( clmNms,0,names,0,dtSize );
    086                data    = new Object[dtSize];
    087        }
    088
    089        /**
    090         * 名前をセットします。
    091         * 指定のカラム番号が、-1 の場合は、なにもしません。
    092         *
    093         * @param   clmNo        値が変更されるカラム番号
    094         * @param   key  新しい名前
    095         */
    096        public void setName( final int clmNo,final String key ) {
    097                if( clmNo >= 0 ) { names[clmNo] = key; }
    098        }
    099
    100        /**
    101         * カラム番号に対するカラム名を取得します。
    102         * 指定のカラム番号が、-1 の場合は、null を返します。
    103         *
    104         * @param   clmNo  カラム番号 最初のカラム番号は0、2番目のカラム番号は 1、などとする。
    105         *
    106         * @return  カラム名
    107         */
    108        public String getName( final int clmNo ) {
    109                return clmNo >= 0 ? names[clmNo] : null ;                       // 6.0.2.5 (2014/10/31) refactoring
    110        }
    111
    112        /**
    113         * カラム名配列を返します。
    114         * 配列オブジェクトは、clone されたコピーを返しますので、
    115         * 内容を書き換えたい場合は、setName() メソッドを使用してください。
    116         *
    117         * @return      カラム名配列
    118         * @og.rtnNotNull
    119         */
    120        @Override       // DataModel
    121        public String[] getNames() {
    122                return names.clone();
    123        }
    124
    125        /**
    126         * column に対応した 値を登録します。
    127         * 指定のカラム番号が、-1 の場合は、なにもしません。
    128         *
    129         * @param   clmNo       値が変更されるカラム番号
    130         * @param   value       新しい値(nullも可)
    131         */
    132        public void setValue( final int clmNo,final Object value ) {
    133                if( clmNo >= 0 ) { data[clmNo] = value; }
    134        }
    135
    136        /**
    137         * column にあるセルの属性値をObjectに変換して返します。
    138         * 指定のカラム番号が、-1 の場合は、null を返します。
    139         *
    140         * @param   clmNo  値が参照されるカラム番号
    141         *
    142         * @return  指定されたセルの値 Object
    143         */
    144        public Object getValue( final int clmNo ) {
    145                return clmNo >= 0 ? data[clmNo] : null ;                        // 6.0.2.5 (2014/10/31) refactoring
    146        }
    147
    148        /**
    149         * row および clm にあるセルの属性値をStringに変換して返します。
    150         *
    151         * @og.rev 6.3.2.0 (2015/07/10) LineModelで、Formatter処理できるように、対応します。
    152         *
    153         * @param   rowNo     値が参照される行
    154         * @param   clmNo     値が参照される列
    155         *
    156         * @return  指定されたセルの値
    157         */
    158        @Override       // DataModel
    159        public Object getValue( final int rowNo, final int clmNo ) {
    160                return getValue( clmNo ) ;              // 6.3.2.0 (2015/07/10)
    161        }
    162
    163        /**
    164         * 属性値配列をセットします。
    165         * このメソッドでは、カラム名配列は更新しません。配列数が異なる場合や、
    166         * 属性値配列が null の場合は設定できません。
    167         * 設定は、配列オブジェクトのコピーをセットしますので、登録元の配列オブジェクトを
    168         * 書き換えた場合でも、このオブジェクトの内部値は変更されませんので、
    169         * 副作用を期待したコーディングは、行わないで下さい。
    170         * 注意：値オブジェクト配列自身はコピーしますが、個々のオブジェクトそのものは、
    171         * arraycopy しているだけです。個々のオブジェクトの状態変化に対しては、
    172         * 各クライアント側で対応が必要です。
    173         *
    174         * @param       values  セットする値配列
    175         * @param       rno             処理中の行番号
    176         */
    177        @Override       // DataModel
    178        public void setValues( final Object[] values, final int rno ) {
    179                if( values == null ) {
    180                        final String errMsg = "値配列が、 null です。row=[" + rno + "]";
    181                        throw new OgRuntimeException( errMsg );
    182                }
    183                else if( names.length != values.length ) {
    184                        final String errMsg = "カラム名配列と異なる要素の属性値配列は登録できません。" + CR
    185                                                        + " names.length=[" + names.length + "],"
    186                                                        + " values.length[" + values.length + "],"
    187                                                        + " row=[" + rno + "]"  + CR
    188                                                        + " names=" + StringUtil.array2csv( names )
    189                                                        + " values=" + Arrays.toString( values ) ;              // 5.1.8.0 (2010/07/01) errMsg 修正
    190                        throw new OgRuntimeException( errMsg );
    191                }
    192
    193                rowNo = rno;
    194                System.arraycopy( values,0,data,0,values.length );
    195        }
    196
    197        /**
    198         * 属性値を配列で返します。
    199         * 配列オブジェクトは、clone されたコピーを返しますので、
    200         * 内容を書き換えたい場合は、setValue() メソッドを使用してください。
    201         *
    202         * @return  指定されたセルの属性値
    203         * @og.rtnNotNull
    204         */
    205        public Object[] getValues() {
    206                return data.clone();
    207        }
    208
    209        /**
    210         * row にあるセルの属性値を配列で返します。
    211         *
    212         * @og.rev 6.3.2.0 (2015/07/10) LineModelで、Formatter処理できるように、対応します。
    213         *
    214         * @param   row     値が参照される行
    215         *
    216         * @return  指定されたセルの属性値
    217         */
    218        @Override       // DataModel
    219        public Object[] getValues( final int row ) {
    220                final String errMsg = "このクラスでは実装されていません。";
    221                throw new UnsupportedOperationException( errMsg );
    222        }
    223
    224        /**
    225         * 行データモデル属性に、処理中の行番号情報を設定します。
    226         * 一般に、setValue( int clm, Object value ) との併用時に使用します。
    227         *
    228         * @param       rno     処理中の行番号
    229         */
    230        public void setRowNo( final int rno ) {
    231                rowNo = rno;
    232        }
    233
    234        /**
    235         * 行データモデル属性の、処理中の行番号情報を返します。
    236         *
    237         * @return  処理中の行番号
    238         */
    239        public int getRowNo() {
    240                return rowNo;
    241        }
    242
    243        /**
    244         * columnName 名称に対応する カラム番号を返します。存在しない場合は、-1 を返します。
    245         *
    246         * @param   columnName  値が参照されるカラム番号
    247         *
    248         * @return  指定されたセルのカラム番号(存在しない場合は、-1)
    249         */
    250        @Override       // DataModel
    251        public int getColumnNo( final String columnName ) {
    252                int clmNo = -1;
    253                if( columnName != null ) {
    254                        for( int i=0; i<dtSize; i++ ) {
    255                                if( columnName.equalsIgnoreCase( names[i] ) ) {
    256                                        clmNo = i;
    257                                        break;
    258                                }
    259                        }
    260                }
    261
    262                return clmNo;
    263        }
    264
    265        /**
    266         * データテーブル内の列の数を返します。
    267         *
    268         * @return  モデルの列数
    269         */
    270        public int size() {
    271                return dtSize ;
    272        }
    273
    274        /**
    275         * この内部データの名前配列を連結した文字列で、出力します。
    276         *
    277         * @return      内部データの名前配列を連結した文字列
    278         */
    279        public String nameLine() {
    280                String rtn = "No Data";
    281
    282                if( dtSize > 0 ) {
    283                        final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    284                        buf.append( "#Name" );
    285                        for( int clm=0; clm<dtSize; clm++ ) {
    286                                buf.append( TAB );
    287                                buf.append( names[clm] );
    288                        }
    289                        rtn = buf.toString() ;
    290                }
    291                return rtn ;
    292        }
    293
    294        /**
    295         * この内部データの名前配列を連結した文字列で、出力します。
    296         *
    297         * @return      名前配列を連結した文字列
    298         */
    299        public String dataLine() {
    300                String rtn = "No Data";
    301
    302                if( dtSize > 0 ) {
    303                        final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    304                        buf.append( rowNo );
    305                        for( int clm=0; clm<dtSize; clm++ ) {
    306                                buf.append( TAB );
    307                                buf.append( data[clm] );
    308                        }
    309                        rtn = buf.toString() ;
    310                }
    311                return rtn ;
    312        }
    313
    314        /**
    315         * この内部データを見える形で出力します。
    316         *
    317         * @return      内部データを見える形
    318         * @og.rtnNotNull
    319         */
    320        @Override       // Object
    321        public String toString() {
    322                return nameLine() + CR + dataLine() ;
    323        }
    324
    325        /**
    326         * clm のNativeタイプを返します。
    327         * Nativeタイプはorg.opengion.fukurou.model.NativeTypeで定義されています。
    328         *
    329         * @og.rev 4.1.1.2 (2008/02/28) 新規追加
    330         * @og.rev 5.1.8.0 (2010/07/01) NativeType#getType(String) のメソッドを使用するように変更。
    331         *
    332         * @param  clm      値が参照される列
    333         *
    334         * @return Nativeタイプ
    335         * @see org.opengion.fukurou.model.NativeType
    336         */
    337        @Override       // DataModel
    338        public NativeType getNativeType( final int clm ) {
    339                return NativeType.getType( data[clm].toString() );
    340        }
    341}