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