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