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.io; 017 018import org.opengion.fukurou.system.OgRuntimeException ; // 6.4.2.0 (2016/01/29) 019 020import org.opengion.hayabusa.db.ColumnActionListener; // 6.2.2.0 (2015/03/27) 021 022/** 023 * 指定の区切り記号(初期値:タブ区切り)ファイルの読み取りクラスです。 024 * 025 * 名前、データの入力部のみオーバーライドすれば、各種入力フォーマットに合わせた 026 * サブクラスを実現する事が可能です。 027 * 028 * @og.group ファイル入力 029 * 030 * @version 4.0 031 * @author Kazuhiko Hasegawa 032 * @since JDK5.0, 033 */ 034public abstract class AbstractTableReader implements TableReader { 035 /** このプログラムのVERSION文字列を設定します。 {@value} */ 036 private static final String VERSION = "8.5.4.2 (2024/01/12)" ; 037 038 /** システムの改行コードを設定します。*/ 039 040 /** 区切り文字列 */ 041 protected String separator = TAB_SEPARATOR; // 6.2.0.0 (2015/02/27) 項目区切り文字。protected化 042 043 private ColumnActionListener listener ; // 6.2.2.0 (2015/03/27) 044 045 // 3.5.4.5 (2004/01/23) カラム名の外部指定を出来る様にする。 046 /** カラム名 */ 047 // 6.1.0.0 (2014/12/26) 読み取り対象外のカラム列を、外部(タグ)より指定する。 048 protected String columns ; // 外部指定のカラム名 ( 4.3.4.7 (2009/01/22) protectedに変更 ) 049 private boolean useNumber = true; // 3.7.0.5 (2005/04/11) 050 private int skipRowCount; // 5.1.6.0 (2010/05/01) データの読み飛ばし設定 051 052 // 5.2.1.0 (2010/10/01) コードリソース毎のラベル逆引きマップ 053 054 // 6.2.0.0 (2015/02/27) TableReader クラスの呼び出し元メソッドの共通化(EXCEL,TEXT) 055 /** シート名 */ 056 protected String sheetName ; // 3.5.4.2 (2003/12/15) 057 /** シート番号 */ 058 protected String sheetNos ; // 5.5.7.2 (2012/10/09) 059 /** カラム名(CSV形式) */ 060 protected String constKeys ; // 5.5.8.2 (2012/11/09) 固定値となるカラム名(CSV形式) 061 /** 固定値となるアドレス */ 062 protected String constAdrs ; // 5.5.8.2 (2012/11/09) 固定値となるアドレス(行-列,行-列,・・・) 063 /** BREAK条件 */ 064 protected String nullBreakClm ; // 5.5.8.2 (2012/11/09) 取込み条件/Sheet BREAK条件 065 /** 行読み飛ばし */ 066 protected String nullSkipClm ; // 6.2.3.0 (2015/05/01) 行読み飛ばし 067 068 private boolean useDebug ; // 5.5.7.2 (2012/10/09) デバッグ情報の出力するかどうか 069 070 /** 071 * デフォルトコンストラクター 072 * 073 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 074 */ 075 protected AbstractTableReader() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 076 077 /** 078 * DBColumn オブジェクトをDBTable に設定します。 079 * 080 * ここでは、omitNames 属性を加味した、カラム名を作成します。 081 * その際、ゼロ文字列のカラム名は、omit します。 082 * 戻り値は、新しいカラム数(omitNames を加味、ゼロ文字列のカラムも除去)です。 083 * 084 * ※ 6.1.0.0 (2014/12/26) で、omitNames 属性を追加します。 085 * これに伴い、従来は、EXCELのみ、#NAME で、ゼロ文字列のカラム名や 086 * columns 指定で、a,b,,,,,,x のようなカラム名指定で、カラム飛ばしを 087 * 実装していましたが、その他の Reader でも、対応します。 088 * これは、互換性に影響しますので、ご注意ください。 089 * (読み込んでも、カラム名が無いので、使えなかったと思いますけど…) 090 * 091 * @og.rev 3.5.4.2 (2003/12/15) private を protected に変更。 092 * @og.rev 3.5.4.5 (2004/01/23) DBColumn 配列に値をセットします。 093 * @og.rev 5.2.1.0 (2010/10/01) useRenderer対応(コードリソース毎のラベル逆引き) 094 * @og.rev 6.1.0.0 (2014/12/26) omitNames 属性を追加 095 * @og.rev 6.2.1.0 (2015/03/13) ロングラベルから、コード値を見つける機能を、廃止します。 096 * @og.rev 6.2.2.0 (2015/03/27) ColumnActionListener 対応。 097 * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 098 * @og.rev 8.5.4.2 (2024/01/12) PMD 7.0.0 LinguisticNaming 対応 099 * 100 * @param names カラム名配列 101// * @return 新しいカラム数(omitNames を加味、ゼロ文字列のカラムも除去) 102 */ 103// protected int setTableDBColumn( final String[] names ) { 104 protected void setTableDBColumn( final String[] names ) { 105 // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 106 if( listener == null ) { 107 final String errMsg = "#setColumnActionListener(ColumnActionListener)を先に実行しておいてください。" ; 108 throw new OgRuntimeException( errMsg ); 109 } 110 111 listener.columnNames( names ); // 6.2.2.0 (2015/03/27) 112 113// return names == null ? 0 : names.length; 114 } 115 116 /** 117 * #NAME のオリジナルカラム名配列がそろった段階で、イベントが発生します。 118 * 119 * @og.rev 7.3.1.3 (2021/03/09) #NAMEのオリジナルを取得できるようにします。 120 * @og.rev 8.0.0.0 (2021/08/20) spotbugs:Bug kind and pattern: UwF - UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR 121 * 122 * @param names カラム名配列 123 */ 124 protected void setOriginalNames( final String[] names ) { 125 // 8.0.0.0 (2021/08/20) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(spotbugs) 126 if( listener == null ) { 127 final String errMsg = "#setColumnActionListener(ColumnActionListener)を先に実行しておいてください。" ; 128 throw new OgRuntimeException( errMsg ); 129 } 130 131 listener.originalNames( names ); 132 } 133 134 /** 135 * DBTableModelオブジェクトに、1行分のデータを追加します。 136 * これ自体は、メソッドの共通化による 拡張をしやすくするために用意しました。 137 * 138 * @og.rev 5.2.1.0 (2010/10/01) 新規作成 139 * @og.rev 6.2.0.0 (2015/02/27) コードリソースの逆引き処理の前に、Key:Val 分解を実行する。 140 * @og.rev 6.2.1.0 (2015/03/13) ロングラベルから、コード値を見つける機能を、廃止します。 141 * @og.rev 6.2.2.0 (2015/03/27) ColumnActionListener 対応。 142 * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 143 * 144 * @param values 1行分のデータ配列 145 * @param rowNo 行番号 146 */ 147 protected void setTableColumnValues( final String[] values, final int rowNo ) { 148 // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 149 if( listener == null ) { 150 final String errMsg = "#setColumnActionListener(ColumnActionListener)を先に実行しておいてください。" ; 151 throw new OgRuntimeException( errMsg ); 152 } 153 154 listener.values( values,rowNo ); // 6.2.2.0 (2015/03/27) 155 } 156 157 /** 158 * 新しくEXCELのシートを処理する際に、シート名をセットするときに呼び出されます。 159 * EXCEL関係の処理の場合のみ呼び出されます。 160 * 161 * @og.rev 7.3.1.1 (2021/02/25) 現在実行中のシート名をセットする 162 * 163 * @param sheetName 現在実行中のシート名 164 */ 165 protected void shtName( final String sheetName ) { 166 // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 167 if( listener == null ) { 168 final String errMsg = "#setColumnActionListener(ColumnActionListener)を先に実行しておいてください。" ; 169 throw new OgRuntimeException( errMsg ); 170 } 171 172 listener.shtName( sheetName ); 173 } 174 175 /** 176 * データを読み込む場合の区切り文字をセットします。 177 * 178 * なお、このメソッドは、サブクラスによっては使用しない場合があります。 179 * もし、使用しないサブクラスを作成する場合は、UnsupportedOperationException 180 * を throw するようにサブクラスで実装して下さい。 181 * 182 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 183 * 184 * @param sep 区切り文字 185 */ 186 @Override // TableReader 187 public void setSeparator( final String sep ) { 188 if( sep != null ) { this.separator = sep; } 189 } 190 191 /** 192 * DBTableModelのデータとしてEXCELファイルを読み込むときのシート名を設定します。 193 * これにより、複数の形式の異なるデータを順次読み込むことや、シートを指定して 194 * 読み取ることが可能になります。 195 * sheetNos と sheetName が同時に指定された場合は、sheetNos が優先されます。エラーにはならないのでご注意ください。 196 * のでご注意ください。 197 * このメソッドは、isExcel() == true の場合のみ利用されます。 198 * 199 * ※ このクラスでは実装されていません。 200 * 201 * @og.rev 3.5.4.2 (2003/12/15) 新規追加 202 * @og.rev 6.2.0.0 (2015/02/27) TableReader クラスの呼び出し元メソッドの共通化(EXCEL,TEXT) 203 * 204 * @param sheetName シート名 205 */ 206 @Override // TableReader 207 public void setSheetName( final String sheetName ) { 208 this.sheetName = sheetName; 209 } 210 211 /** 212 * EXCELファイルを読み込むときのシート番号を指定します(初期値:0)。 213 * 214 * EXCEL読み込み時に複数シートをマージして取り込みます。 215 * シート番号は、0 から始まる数字で表します。 216 * ヘッダーは、最初のシートのカラム位置に合わせます。(ヘッダータイトルの自動認識はありません。) 217 * よって、指定するシートは、すべて同一レイアウトでないと取り込み時にカラムのずれが発生します。 218 * 219 * シート番号の指定は、CSV形式で、複数指定できます。また、N-M の様にハイフンで繋げることで、 220 * N 番から、M 番のシート範囲を一括指定可能です。また、"*" による、全シート指定が可能です。 221 * これらの組み合わせも可能です。( 0,1,3,5-8,10-* ) 222 * ただし、"*" に関しては例外的に、一文字だけで、すべてのシートを表すか、N-* を最後に指定するかの 223 * どちらかです。途中には、"*" は、現れません。 224 * シート番号は、重複(1,1,2,2)、逆転(3,2,1) での指定が可能です。これは、その指定順で、読み込まれます。 225 * sheetNos と sheetName が同時に指定された場合は、sheetNos が優先されます。エラーにはならないのでご注意ください。 226 * このメソッドは、isExcel() == true の場合のみ利用されます。 227 * 228 * 初期値は、0(第一シート) です。 229 * 230 * ※ このクラスでは実装されていません。 231 * 232 * @og.rev 5.5.7.2 (2012/10/09) 新規追加 233 * @og.rev 6.2.0.0 (2015/02/27) TableReader クラスの呼び出し元メソッドの共通化(EXCEL,TEXT) 234 * 235 * @param sheetNos EXCELファイルのシート番号(0から始まる) 236 * @see #setSheetName( String ) 237 */ 238 @Override // TableReader 239 public void setSheetNos( final String sheetNos ) { 240 this.sheetNos = sheetNos; 241 } 242 243 /** 244 * 固定値となるカラム名(CSV形式)と、constAdrs 固定値となるアドレス(行-列,行-列,・・・)を設定します。 245 * 246 * アドレスは、EXCEL上の行-列をCSV形式で指定します。 247 * 行列は、EXCELオブジェクトに準拠するため、0から始まる整数です。 248 * 0-0 ⇒ A1 , 1-0 ⇒ A2 , 0-1 ⇒ B1 になります。 249 * これにより、シートの一か所に書かれている情報を、DBTableModel のカラムに固定値として 250 * 設定することができます。 251 * 例として、DB定義書で、テーブル名をシートの全レコードに設定したい場合などに使います。 252 * このメソッドは、isExcel() == true の場合のみ利用されます。 253 * 254 * 5.7.6.3 (2014/05/23) より、 255 * ①EXCEL表記に準拠した、A1,A2,B1 の記述も処理できるように対応します。 256 * なお、A1,A2,B1 の記述は、必ず、英字1文字+数字 にしてください。(A~Zまで) 257 * ②処理中のEXCELシート名をカラムに割り当てるために、"SHEET" という記号に対応します。 258 * 例えば、sheetConstKeys="CLM,LANG,NAME" とし、sheetConstAdrs="0-0,A2,SHEET" とすると、 259 * NAMEカラムには、シート名を読み込むことができます。 260 * これは、内部処理の簡素化のためです。 261 * 262 * 例として、DB定義書で、テーブル名をシートの全レコードに設定したい場合などに使います。 263 * このメソッドは、isExcel() == true の場合のみ利用されます。 264 * 265 * @og.rev 5.5.8.2 (2012/11/09) 新規追加 266 * 267 * @param constKeys 固定値となるカラム名(CSV形式) 268 * @param constAdrs 固定値となるアドレス(行-列,行-列,・・・) 269 */ 270 @Override // TableReader 271 public void setSheetConstData( final String constKeys,final String constAdrs ) { 272 this.constKeys = constKeys; 273 this.constAdrs = constAdrs; 274 } 275 276 /** 277 * ここに指定されたカラム列に NULL が現れた時点で読み取りを中止します。 278 * 279 * これは、指定のカラムは必須という事を条件に、そのレコードだけを読み取る処理を行います。 280 * 複数Sheetの場合は、次のSheetを読みます。 281 * 現時点では、Excel の場合のみ有効です。 282 * 283 * @og.rev 5.5.8.2 (2012/11/09) 新規追加 284 * @og.rev 6.2.0.0 (2015/02/27) TableReader クラスの呼び出し元メソッドの共通化(EXCEL,TEXT) 285 * 286 * @param clm カラム列 287 */ 288 @Override // TableReader 289 public void setNullBreakClm( final String clm ) { 290 nullBreakClm = clm; 291 } 292 293 /** 294 * ここに指定されたカラム列に NULL が現れたレコードは読み飛ばします。 295 * 296 * 例えば、更新対象カラムで、null の場合は、何もしない、などのケースで使用できます。 297 * 複数カラムの場合は、AND条件やOR条件などが、考えられるため、 298 * カラムを一つにまとめて、指定してください。 299 * 300 * @og.rev 6.2.3.0 (2015/05/01) 行読み飛ばし nullSkipClm追加 301 * 302 * @param clm カラム列 303 */ 304 @Override // TableReader 305 public void setNullSkipClm( final String clm ) { 306 nullSkipClm = clm; 307 } 308 309 /** 310 * 読み取り元ファイルのカラム列を、外部(タグ)より指定します。 311 * ファイルに記述された #NAME より優先して使用されます。 312 * 313 * @og.rev 3.5.4.5 (2004/01/23) 新規作成 314 * 315 * @param clms 読み取り元ファイルのカラム列(CSV形式) 316 */ 317 @Override // TableReader 318 public void setColumns( final String clms ) { 319 columns = clms ; 320 } 321 322 /** 323 * 行番号情報を指定[true:使用している/false:していない]します(初期値:true)。 324 * 325 * 通常のフォーマットでは、各行の先頭に行番号が出力されています。 326 * 読み取り時に、#NAME 属性を使用する場合は、この行番号を無視しています。 327 * #NAME 属性を使用せず、columns 属性でカラム名を指定する場合(他システムの 328 * 出力ファイルを読み取るケース等)では、行番号も存在しないケースがあり、 329 * その様な場合に、useNumber="false" を指定すれば、データの最初から読み取り始めます。 330 * この場合、出力データのカラムの並び順が変更された場合、columns 属性も 331 * 指定しなおす必要がありますので、できるだけ、#NAME 属性を使用するように 332 * してください。 333 * なお、EXCEL 入力には、この設定は適用されません。(暫定対応) 334 * 初期値は、true(使用する) です。 335 * 336 * @og.rev 3.7.0.5 (2005/04/11) 新規追加 337 * 338 * @param useNumber 行番号情報 [true:使用する/false:使用しない] 339 */ 340 @Override // TableReader 341 public void setUseNumber( final boolean useNumber ) { 342 this.useNumber = useNumber ; 343 } 344 345 /** 346 * データの読み始めの初期値を取得します。 347 * 348 * TAB区切りテキストやEXCEL等のデータの読み始めの初期値を指定します。 349 * ファイルの先頭行が、0行としてカウントしますので、設定値は、読み飛ばす 350 * 件数になります。(1と指定すると、1件読み飛ばし、2行目から読み込みます。) 351 * 読み飛ばしは、コメント行などは、無視しますので、実際の行数分読み飛ばします。 352 * #NAME属性や、columns 属性は、有効です。 353 * 354 * @og.rev 5.1.6.0 (2010/05/01) 新規作成 355 * 356 * @return 読み始めの初期値 357 */ 358 public int getSkipRowCount() { 359 return skipRowCount ; 360 } 361 362 /** 363 * データの読み飛ばし件数を設定します。 364 * 365 * TAB区切りテキストやEXCEL等のデータの読み始めの初期値を指定します。 366 * ファイルの先頭行が、0行としてカウントしますので、設定値は、読み飛ばす 367 * 件数になります。(1と指定すると、1件読み飛ばし、2行目から読み込みます。) 368 * 読み飛ばしは、コメント行などは、無視しますので、実際の行数分読み飛ばします。 369 * #NAME属性や、columns 属性は、有効です。 370 * 371 * @og.rev 5.1.6.0 (2010/05/01) 新規作成 372 * 373 * @param count 読み始めの初期値 374 */ 375 @Override // TableReader 376 public void setSkipRowCount( final int count ) { 377 skipRowCount = count; 378 } 379 380 /** 381 * 行番号情報を、使用している(true)/していない(false)を返します。 382 * 383 * 通常のフォーマットでは、各行の先頭に行番号が出力されています。 384 * 読み取り時に、#NAME 属性を使用する場合は、この行番号を無視しています。 385 * #NAME 属性を使用せず、columns 属性でカラム名を指定する場合(他システムの 386 * 出力ファイルを読み取るケース等)では、行番号も存在しないケースがあり、 387 * その様な場合に、useNumber="false" を指定すれば、データの最初から読み取り始めます。 388 * この場合、出力データのカラムの並び順が変更された場合、columns 属性も 389 * 指定しなおす必要がありますので、できるだけ、#NAME 属性を使用するように 390 * してください。 391 * なお、EXCEL 入力には、この設定は適用されません。(暫定対応) 392 * 初期値は、true(使用する) です。 393 * 394 * @og.rev 3.7.0.5 (2005/04/11) 新規追加 395 * @og.rev 4.0.0.0 (2007/07/20) メソッド名変更(getUseNumber() ⇒ isUseNumber()) 396 * 397 * @return 行番号情報を、使用している(true)/していない(false)を指定 398 */ 399 protected boolean isUseNumber() { 400 return useNumber ; 401 } 402 403 /** 404 * ColumnActionListenerオブジェクトを設定します。 405 * 406 * ColumnActionListenerオブジェクトは、カラム名配列設定時と、それに対応する値配列設定時に 407 * 呼ばれるイベントリスナーです。 408 * 具体的なテーブル処理は、このイベントを使用して書き込みを行います。 409 * 410 * @og.rev 6.2.2.0 (2015/03/27) 新規作成 411 * 412 * @param listener ColumnActionListenerオブジェクト 413 */ 414 @Override // TableReader 415 public void setColumnActionListener( final ColumnActionListener listener ) { 416 this.listener = listener; 417 } 418 419 /** 420 * デバッグ情報を出力するかどうか[true:する/false:しない]を指定します。 421 * 422 * EXCELなどを読み取る場合、シートマージで読み取ると、エラー時の行番号が、連番になるため、 423 * どのシートなのか、判らなくなります。 424 * そこで、どうしてもわからなくなった場合に備えて、デバッグ情報を出力できるようにします。 425 * 通常は使用しませんので、設定を無視します。 426 * 初期値は、false:デバッグ情報を出力しない です。 427 * 428 * @og.rev 5.5.7.2 (2012/10/09) 新規作成 429 * 430 * @param useDebug デバッグ出力するか [true:する/false:しない] 431 */ 432 @Override // TableReader 433 public void setDebug( final boolean useDebug ) { 434 this.useDebug = useDebug; 435 } 436 437 /** 438 * デバッグ情報を出力するかどうか[true:する/false:しない]を取得します。 439 * 440 * EXCELなどを読み取る場合、シートマージで読み取ると、エラー時の行番号が、連番になるため、 441 * どのシートなのか、判らなくなります。 442 * そこで、どうしてもわからなくなった場合に備えて、デバッグ情報を出力できるようにします。 443 * 444 * @og.rev 5.5.7.2 (2012/10/09) 新規作成 445 * 446 * @return デバッグ出力 [true:する/false:しない] 447 */ 448 protected boolean isDebug() { 449 return useDebug ; 450 } 451}