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 は、データの1行分を管理する為の TableModel と類似の実装クラスです。
029 *
030 * データの1行分を 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}