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.taglib; 017 018import org.opengion.fukurou.system.OgRuntimeException; // 6.4.2.0 (2016/01/29) 019import org.opengion.fukurou.system.OgCharacterException; // 6.5.0.1 (2016/10/21) 020import org.opengion.fukurou.system.ThrowUtil; // 6.4.2.0 (2016/01/29) 021import org.opengion.fukurou.util.ErrorMessage; 022import org.opengion.fukurou.util.StringUtil; 023import org.opengion.fukurou.util.ToString; // 6.1.1.0 (2015/01/17) 024import org.opengion.fukurou.util.FileInfo; // 6.2.0.0 (2015/02/27) 025import org.opengion.fukurou.util.ArraySet; // 6.4.3.4 (2016/03/11) 026import org.opengion.hayabusa.common.HybsSystem; 027import org.opengion.hayabusa.common.HybsSystemException; 028import org.opengion.hayabusa.common.HybsOverflowException; // 6.2.2.0 (2015/03/27) 029import org.opengion.hayabusa.db.DBTableModelUtil; // 6.2.1.0 (2015/03/13) 030import org.opengion.hayabusa.db.DBTableModel; 031import org.opengion.hayabusa.db.DBColumn; 032import org.opengion.hayabusa.db.ColumnActionListener; // 6.2.2.0 (2015/03/27) 033import org.opengion.hayabusa.io.TableReader; 034import org.opengion.hayabusa.io.HybsFileOperationFactory; // 8.0.0.1 (2021/10/08) 035 036import static org.opengion.fukurou.util.StringUtil.nval; 037import static org.opengion.fukurou.system.HybsConst.BR; // 6.1.0.0 (2014/12/26) refactoring 038 039import java.util.Locale; 040import java.util.List; // 6.2.5.0 (2015/06/05) 041import java.util.Set; // 6.4.3.4 (2016/03/11) 042import java.util.ArrayList; // 6.2.5.0 (2015/06/05) 043import java.util.Map; // 6.4.6.0 (2016/05/27) 044import java.util.HashMap; // 6.4.6.0 (2016/05/27) 045import java.io.File; 046 047/** 048 * 指定のファイルを DBTableModelオブジェクトに読み取るファイル入力タグです。 049 * 050 * データ(DBTableModel)と、コントローラ(ReadTableタグ)を与えて、外部からコントロールすることで、 051 * 各種形式で データ(DBTableModel)を表示させることが できます。 052 * ReadTableタグ に対して、コマンドを与えることにより、内部のコントローラの実装に対応した 053 * 形式でデータを作成します。 054 * すべての読取の初期クラス名を リソースファイルの TABLE_READER_DEFAULT_CLASS で指定可能です。 055 * その場合、AutoReader を指定すると、Excel と Text(テキスト) を以下の順番で試します。 056 * Excel,Calc,Text(UnicodeLittle),Text(Windows-31J),Text(UTF-8),Text(EUC-JP),POI 057 * UTF-8 のTEXTとWindows-31JのTEXTは、ヘッダー部での区別ができないため、正確なTextの自動読取できません。 058 * 059 * ※ 6.2.5.0 (2015/06/05) 仕様変更 060 * ・AutoReader で、encode を指定すると、Text(encode) を先に試します。 061 * ・Textで、encode を指定しない場合は、システム変数の FILE_ENCODE を使用します。 062 * 063 * 入力件数を"DB.COUNT" キーでリクエストにセットしています。 064 * 065 * ※ 7.3.1.3 (2021/03/09) DB.NAMES , DB.ORGNAMES 066 * #NAME や columns で指定したカラムは、{@DB.NAMES} で取り出すことが可能です。 067 * ファイルにかかれた、オリジナルの #NAME は、{@DB.ORGNAMES} で取り出すことが可能です。 068 * 069 * @og.formSample 070 * ●形式: 071 * <og:readTable 072 * command = "NEW" 073 * fileURL = "{@USER.ID}" 読取元ディレクトリ名 074 * filename = "{@filename}" 読取元ファイル名 075 * encode = "UnicodeLittle" 読取元ファイルエンコード名 076 * maxRowCount = "10000" 読取最大件数(初期値:0:[無制限]) 077 * /> 078 * ●body:なし 079 * 080 * ●Tag定義: 081 * <og:readTable 082 * readerClass 【TAG】実際に読み出すクラス名の略称(TableReader_**** の ****)をセットします 083 * (初期値:TABLE_READER_DEFAULT_CLASS[={@og.value SystemData#TABLE_READER_DEFAULT_CLASS}]) 084 * command 【TAG】コマンド (NEW,RENEW)をセットします(初期値:NEW) 085 * fileURL 【TAG】読取元ディレクトリ名を指定します(初期値:FILE_URL) 086 * filename 【TAG】ファイルを読み出すときのファイル名をセットします (初期値:FILE_FILENAME[=file.xls]) 087 * encode 【TAG】ファイルを読み出すときのファイルエンコーディング名をセットします(初期値:FILE_ENCODE) 088 * skipRowCount 【TAG】(通常は使いません)データの読み飛ばし件数を設定します 089 * maxRowCount 【TAG】読取時の最大取込件数をセットします (初期値:0:[無制限]) 090 * errRowCount 【TAG】読取時の最大エラー件数をセットします (初期値:{@og.value #ERROR_ROW_COUNT})(0:[無制限]) 091 * separator 【TAG】可変長ファイルを読み出すときの項目区切り文字をセットします 092 * columns 【TAG】読取元ファイルのカラム列を、外部(タグ)よりCSV形式で指定します 093 * omitNames 【TAG】読取対象外のカラム列を、外部(タグ)よりCSV形式で指定します 094 * modifyType 【TAG】ファイル取込時の モディファイタイプ(A(追加),C(更新),D(削除))を指定します 095 * displayMsg 【TAG】query の結果を画面上に表示するメッセージIDを指定します(初期値:VIEW_DISPLAY_MSG[={@og.value SystemData#VIEW_DISPLAY_MSG}])) 096 * overflowMsg 【TAG】読取データが最大検索数をオーバーした場合に表示するメッセージリソースIDを指定します (初期値:MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました]) 097 * notfoundMsg 【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした]) 098 * ※ sheetName 【TAG】EXCELファイルを読み込むときのシート名を設定します(初期値:指定なし) 099 * ※ sheetNos 【TAG】EXCELファイルを読み込むときのシート番号を複数設定できます(初期値:0) 100 * ※ sheetConstKeys 【TAG】EXCELファイルを読み込むときの固定値となるカラム名(CSV形式) 101 * ※ sheetConstAdrs 【TAG】EXCELファイルを読み込むときの固定値となるアドレス(行-列,行-列,・・・) 102 * nullBreakClm 【TAG】カラム列に NULL が現れた時点で読取を中止します(複数Sheetの場合は、次のSheetを読みます)。 103 * nullSkipClm 【TAG】カラム列に NULL が現れたレコードは読み飛ばします。 104 * useNumber 【TAG】行番号情報を、使用している/していない[true/false]を指定します(初期値:true) 105 * useRepeatClms 【TAG】読取処理で横持ちデータの繰り返しが存在する場合に、trueを指定します(初期値:false) 7.3.0.0 (2021/01/06) 106 * useRenderer 【TAG】読取処理でKEY:VAL形式のコードリソースから、KEYを取り出す処理を行うかどうかを指定します(初期値:USE_TABLE_READER_RENDERER[=false]) 107 * adjustColumns 【TAG】読取元ファイルのデータ変換を行うカラム列をカンマ指定します("*" で全カラム) 108 * checkColumns 【TAG】読取元ファイルの整合性チェックを行うカラム列をカンマ指定します("*" で全カラム) 109 * useStrict 【TAG】整合性チェック時に、厳密にチェックするかどうか[true/false]を指定します(初期値:true) 7.3.2.0 (2021/03/19) 110 * nullCheck 【TAG】NULL チェックすべきカラム列をCSV形式(CSV形式)で指定します 111 * matchKeys 【TAG】レコードの読取条件指定時のカラム列をCSV形式で指定します 6.4.6.0 (2016/05/27) 112 * matchVals 【TAG】レコードの読取条件指定時のカラム列に対応する正規表現データをCSV形式で指定します 6.4.6.0 (2016/05/27) 113 * language 【TAG】タグ内部で使用する言語コード[ja/en/zh/…]を指定します 114 * stopZero 【TAG】読込件数が0件のとき処理を続行するかどうか[true/false]を指定します(初期値:false[続行する]) 115 * mainTrans 【TAG】(通常は使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:false) 116 * tableId 【TAG】(通常は使いません)sessionから所得する DBTableModelオブジェクトの ID 117 * scope 【TAG】キャッシュする場合のスコープ[request/page/session/application]を指定します(初期値:session) 118 * useSLabel 【TAG】7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false) 119 * useLocal 【TAG】システム定数でクラウド設定されていても、クラウド環境を使用しない場合、trueを指定します(初期値:false) 8.0.1.0 (2021/10/29) 120 * caseKey 【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 5.7.7.2 (2014/06/20) 121 * caseVal 【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 5.7.7.2 (2014/06/20) 122 * caseNN 【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない) 5.7.7.2 (2014/06/20) 123 * caseNull 【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない) 5.7.7.2 (2014/06/20) 124 * caseIf 【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない) 125 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 126 * /> 127 * 128 * ●使用例 129 * 130 * <og:readTable 131 * command = "NEW" 132 * readerClass = "Text" テキストファイルの読取 133 * modifyType = "{@modifyType}" 読取時のモディファイタイプ(A,C等) 134 * fileURL = "{@USER.ID}" 読取元ディレクトリ名 135 * filename = "{@filename}" 読取元ファイル名 136 * encode = "Shift_JIS" 読取元ファイルエンコード名 137 * maxRowCount = "10000" 読取最大件数(0:[無制限]) 138 * columns = "OYA,KO,HJO,SU,DYSTR,DYEND" #NAME に対応するカラム列 139 * useNumber = "false" 行番号の存在しないデータを読取ます。 140 * adjustColumns = "OYA,KO,HJO,SU" データ変換するカラム列("*" で全カラム) 141 * checkColumns = "OYA,KO,HJO,SU" 整合性チェックするカラム列("*" で全カラム) 142 * nullCheck = "OYA,KO,SU" NULLチェックを実行します("*" で全カラム) 143 * stopZero = "true" 取得0件の場合に以降の処理を停止します 144 * skipRowCount = "4" データの読み飛ばし件数(読み込み開始は、この数字+1行目から) 145 * /> 146 * 147 * @og.group ファイル入力 148 * 149 * @version 4.0 150 * @author Kazuhiko Hasegawa 151 * @since JDK5.0, 152 */ 153public class ReadTableTag extends CommonTagSupport { 154 /** このプログラムのVERSION文字列を設定します。 {@value} */ 155 private static final String VERSION = "8.1.2.3 (2022/05/20)" ; 156 private static final long serialVersionUID = 812320220520L ; 157 158 private static final int ERROR_ROW_COUNT = 200 ; // 4.0.0 (2007/05/25) 159 160 /** command 引数に渡す事の出来る コマンド 新規作成 {@value} */ 161 public static final String CMD_NEW = "NEW" ; 162 /** command 引数に渡す事の出来る コマンド 再検索 {@value} */ 163 public static final String CMD_RENEW = "RENEW" ; 164 165 // 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。 166 private static final Set<String> COMMAND_SET = new ArraySet<>( CMD_NEW , CMD_RENEW ); 167 168 // 6.2.0.0 (2015/02/27) AutoReaderの対応方法変更。拡張子に応じて、チェック対象を変更する。null は全対象 169 // 6.2.2.0 (2015/03/27) マクロ付Excel(.xlsm)対応 170 // 6.2.5.0 (2015/06/05) 文字列配列から、内部クラスに変更 171 // 6.4.5.1 (2016/04/28) 順番の変更と、CSV対応 172 173 private static final List<AutoReaderParam> AUTO_READER_PARAM = new ArrayList<>() ; 174 static { 175 AUTO_READER_PARAM.add( new AutoReaderParam( "Excel" , null , "xls,xlsx,xlsm" ) ); 176 AUTO_READER_PARAM.add( new AutoReaderParam( "CSV" , "Windows-31J" , "csv" ) ); // 6.4.5.1 (2016/04/28) 追加 177 AUTO_READER_PARAM.add( new AutoReaderParam( "CSV" , "UTF-8" , "csv" ) ); // 6.4.5.1 (2016/04/28) 追加 178 AUTO_READER_PARAM.add( new AutoReaderParam( "Text" , "UnicodeLittle" , null ) ); 179 AUTO_READER_PARAM.add( new AutoReaderParam( "Text" , "Windows-31J" , null ) ); 180 AUTO_READER_PARAM.add( new AutoReaderParam( "Text" , "UTF-8" , null ) ); 181 AUTO_READER_PARAM.add( new AutoReaderParam( "Text" , "EUC-JP" , null ) ); 182 AUTO_READER_PARAM.add( new AutoReaderParam( "POI" , null , "ppt,pptx,doc,docx,xls,xlsx,xlsm" ) ); // 6.2.5.0 (2015/06/05) 追加 183 AUTO_READER_PARAM.add( new AutoReaderParam( "Calc" , null , "ods" ) ); // 6.4.5.1 (2016/04/28) 位置変更 184 } 185 186 /** 項目区切り文字 */ 187 protected String separator = TableReader.TAB_SEPARATOR; // 項目区切り文字 6.2.0.0 (2015/02/27) protected化 188 /** ファイルURL */ 189 private String fileURL = HybsSystem.sys( "FILE_URL" ); 190 /** ファイル名 */ 191 private String filename = HybsSystem.sys( "FILE_FILENAME" ); 192 /** ファイルエンコーディング */ 193 protected String encode ; // 6.2.5.0 (2015/06/05) 194 /** 読取クラス名 */ 195 protected String readerClass ; // 6.2.0.0 (2015/02/27) protected化 196 /** 最大行 */ 197 protected int maxRowCount ; // 6.2.0.0 (2015/02/27) 初期値を無制限に変更 198 /** ディスプレイメッセージ */ 199 protected String displayMsg = HybsSystem.sys( "VIEW_DISPLAY_MSG" ); // 6.2.0.0 (2015/02/27) protected化 200 /** 読取データが最大検索数をオーバーした場合に表示するメッセージリソースIDを指定する */ 201 private String overflowMsg = "MSG0007"; // 検索結果が、制限行数を超えましたので、残りはカットされました。 202 /** 検索結果がゼロ件の場合に表示するメッセージリソースIDを指定する */ 203 private String notfoundMsg = "MSG0077"; // 対象データはありませんでした。 204 /** 実行件数 */ 205 protected int executeCount = -1; // 検索/実行件数 206 /** ファイル取込時の モディファイタイプ */ 207 private String modifyType ; 208 209 private transient DBTableModel table ; 210 /** コマンド */ 211 private String command = CMD_NEW; 212 /** テーブルID */ 213 private String tableId = HybsSystem.TBL_MDL_KEY; 214 /** シート名 */ 215 protected String sheetName ; // 3.5.4.2 (2003/12/15) 216 /** シート番号 */ 217 protected String sheetNos ; // 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるようにする。 218 /** 固定値となるカラム名 */ 219 protected String sheetConstKeys ; // 5.5.8.2 (2012/11/09) 固定値となるカラム名(CSV形式) 220 /** 固定値となるアドレス */ 221 protected String sheetConstAdrs ; // 5.5.8.2 (2012/11/09) 固定値となるアドレス(行-列,行-列,・・・) 222 /** 取込み条件/Sheet BREAK条件 */ 223 protected String nullBreakClm ; // 5.5.8.2 (2012/11/09) 取込み条件/Sheet BREAK条件 224 /** 行読み飛ばし */ 225 protected String nullSkipClm ; // 6.2.3.0 (2015/05/01) 行読み飛ばし 226 227 /** 3.5.4.5 (2004/01/23) 外部よりカラム列(CSV形式)を指定できるようにする */ 228 protected String columns ; // 6.2.0.0 (2015/02/27) protected化 229 /** 6.1.0.0 (2014/12/26) 読取対象外のカラム列を、外部(タグ)より指定する */ 230 protected boolean useNumber = true; // 3.7.0.5 (2005/04/11) 231// /** 7.3.0.0 (2021/01/06) useRepeatClms 属性を追加 */ 232// protected boolean useRepeatClms ; // 7.3.0.0 (2021/01/06) 233 /** stopZero属性 */ 234 protected boolean stopZero ; // 4.3.7.0 (2009/06/01) stopZero属性追加 235 236 /** メイントランザクションかどうか */ 237 private boolean isMainTrans = true; // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し 238 /** データの読み飛ばし設定 */ 239 protected int skipRowCount ; // 5.1.6.0 (2010/05/01) データの読み飛ばし設定 240 241 /** 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する */ 242 protected transient ColumnAction clmAct = new ColumnAction(); // 6.3.9.0 (2015/11/06) transient 追加 243 244 // 6.3.6.1 (2015/08/28) DirectTableInsertTag でSQLException発生時にセットする。(暫定対応) 245 // 8.1.1.0 (2022/02/04) sqlError フラグでの判定は、DirectTableInsertTag のみで行います。 246// protected boolean sqlError ; // 6.3.6.1 (2015/08/28) 247 248 /** 7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false) */ 249 protected boolean useSLabel ; 250 /** クラウド設定を使用するかどうか */ 251 private boolean useLocal ; // 8.0.1.0 (2021/10/29) クラウド設定を使用しない場合は、true 252 253 /** 254 * デフォルトコンストラクター 255 * 256 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 257 */ 258 public ReadTableTag() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 259 260 /** 261 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 262 * 263 * @og.rev 3.0.1.4 (2003/03/17) displayMsg が 0Byteの場合は、件数も表示しないように変更。 264 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 265 * @og.rev 3.5.4.1 (2003/12/01) 引数の BufferedReader を、InputStream に変更。 266 * @og.rev 3.5.4.3 (2004/01/05) 引数の InputStream を、 BufferedReader に戻す。 267 * @og.rev 3.5.6.5 (2004/08/09) 暫定的に、DBTableModelを先行削除します。 268 * @og.rev 3.6.0.0 (2004/09/24) DBTableModel の先行削除は、scope="session" の場合のみ。 269 * @og.rev 3.6.0.2 (2004/10/04) 取込時チェック用に、checkColumns,adjustColumns 属性追加 270 * @og.rev 3.6.0.8 (2004/11/19) DBTableModel をセーブする時に、トランザクションチェックを行います。 271 * @og.rev 3.8.5.3 (2006/08/07) readerClassが "Excel"でエラーが発生したとき、もう一度Defaultで再読取を行います。 272 * @og.rev 4.0.0.0 (2007/10/12) checkTableColumn 前に、modifyType 設定を行います。 273 * @og.rev 4.0.0.0 (2007/10/18) メッセージリソース統合( getResource().getMessage ⇒ getResource().getLabel ) 274 * @og.rev 4.3.1.1 (2008/10/08) columnsが指定されている場合は、AutoReader禁止 275 * @og.rev 4.3.7.0 (2009/06/01) stopZero機能,DB.COUNTリクエストキーへ読込件数セットを追加 276 * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。 277 * @og.rev 5.1.8.0 (2010/07/01) AutoReaderのCalc対応 278 * @og.rev 5.1.9.0 (2010/08/01) AutoReaderでのExceptionの判定をThrowableに変更 279 * @og.rev 5.7.1.2 (2013/12/20) tempMsg.toString() ⇒ errMsg 変更 280 * @og.rev 5.7.7.2 (2014/06/20) caseKey,caseVal,caseNN,caseNull 属性を追加 281 * @og.rev 6.0.2.5 (2014/10/31) debug=true 時のエラー情報を増やします。 282 * @og.rev 6.2.0.0 (2015/02/27) TableReader クラスの呼び出し元メソッドの共通化(EXCEL,TEXT) 283 * @og.rev 6.2.0.0 (2015/02/27) EXCEL出力のparamLevel初期値変更 3:標準推奨 → 4:個人設定可 284 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。 285 * @og.rev 6.2.3.0 (2015/05/01) 複数処理を考慮して、例外処理は発行しない。 286 * @og.rev 6.2.3.0 (2015/05/01) columnsが指定されていても、AutoReader を使えるようにします。 287 * @og.rev 6.2.4.2 (2015/05/29) エラーを画面に出します。 288 * @og.rev 6.2.5.0 (2015/06/05) AutoReaderの仕様変更。 289 * @og.rev 6.3.6.1 (2015/08/28) DirectTableInsertTag でSQLException発生時のみ throwする。 290 * @og.rev 6.4.2.0 (2016/01/29) StringUtil#ogStackTrace(Throwable) を、ThrowUtil#ogStackTrace(String,Throwable) に置き換え。 291 * @og.rev 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。 292 * @og.rev 6.4.5.1 (2016/04/28) CSV 指定時は、readerClass="Text" , separator="," に、再設定します。 293 * @og.rev 6.5.0.1 (2016/10/21) Throwable ではなく、OgCharacterException をキャッチして、処理を継続します。 294 * @og.rev 7.0.4.0 (2019/05/31) encode指定時の処理順序変更 295 * @og.rev 7.0.5.0 (2019/09/09) OgCharacterExceptionでは、取りこぼしがあるため、OgRuntimeException も継続処理するように変更。 296 * @og.rev 8.0.0.1 (2021/10/08) クラウド対応 297 * @og.rev 8.0.0.2 (2021/10/15) TableReader系は、クラウドから、ローカルファイルに移してから処理する。 298 * @og.rev 8.1.1.0 (2022/02/04) sqlError フラグでの判定は、DirectTableInsertTag のみで行います。 299 * @og.rev 8.1.2.3 (2022/05/20) readerClass が AutoReader の時、readerClass が Text になるバグ修正 300 * 301 * @return 後続処理の指示 302 */ 303 @Override 304 public int doEndTag() { 305 debugPrint(); // 4.0.0 (2005/02/28) 306 // 5.7.7.2 (2014/06/20) caseKey,caseVal,caseNN,caseNull 属性を追加 307 if( !useTag() ) { return EVAL_PAGE ; } 308 309 int rtnCode = EVAL_PAGE; 310 311 if( check( command, COMMAND_SET ) ) { 312 useMainTrans( isMainTrans ); // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し 313 startQueryTransaction( tableId ); // 3.6.0.8 (2004/11/19) 314 315 // 3.5.6.5 (2004/08/09) 削除するのは、セッションのオブジェクトでよい。 316 // 3.6.0.0 (2004/09/24) 削除するのは、scope="session" の場合のみ。 317 if( "session".equals( getScope() ) ) { 318 removeSessionAttribute( tableId ); 319 removeSessionAttribute( HybsSystem.VIEWFORM_KEY ); 320 } 321 322 // 6.2.5.0 (2015/06/05) AutoReaderの仕様変更。 323 324 // 6.2.0.0 (2015/02/27) EXCEL出力のparamLevel初期値変更 3:標準推奨 → 4:個人設定可 325 if( readerClass == null ) { 326 readerClass = nval( sys( "TABLE_READER_DEFAULT_CLASS" ) , "AutoReader" ); 327 } 328 329 // ファイル の読み込み:AutoReader 処理 330 // 6.2.5.0 (2015/06/05) AutoReaderParam 内部クラスを使用します。 331 final List<AutoReaderParam> readerParam = new ArrayList<>() ; 332 333 if( "AutoReader".equalsIgnoreCase( readerClass ) ) { 334 // 4.3.1.1 (2008/10/08) 335 // // 6.2.3.0 (2015/05/01) columnsが指定されていても、AutoReader を使えるようにします。 336 // if( columns != null && columns.length() > 0 ) { 337 // final String errMsg = "columnsが指定されている場合は、readerClass=\"AutoReader\"は使えません"; 338 // throw new HybsSystemException( errMsg ); // 4.3.4.4 (2009/01/01) 339 // } 340 // 6.2.5.0 (2015/06/05) AutoReaderParam 内部クラスを使用します。 341 // 6.5.0.1 (2016/10/21) encode 指定時の優先は、拡張子が、txt か、csv のみとします。 342 // if( encode != null ) { readerParam.add( new AutoReaderParam( "Text" , encode , null ) ); } // encode 指定時は優先 343// if( encode != null ) { readerParam.add( new AutoReaderParam( "Text" , encode , "csv,txt,xls" ) ); } // encode 指定時は優先 344// if( encode != null ) { readerParam.add( new AutoReaderParam( "Text" , encode , "txt,csv,xls" ) ); } // encode 指定時は優先 7.0.4.0 (2019/05/31) 順序変更 345 if( encode != null ) { 346 readerParam.add( new AutoReaderParam( "Text" , encode , "txt,csv,xls" ) ); // encode 指定時は優先 7.0.4.0 (2019/05/31) 順序変更 347 readerParam.add( new AutoReaderParam( "Text" , encode , null ) ); // 7.1.0.0 (2020/01/20) 拡張子に関係ない分も追加 348 } 349 readerParam.addAll( AUTO_READER_PARAM ); // 標準のパラメータを追加します。 350 } 351 else { 352 // 6.2.5.0 (2015/06/05) readerClass が "Text" で、encode が null の場合は、FILE_ENCODE を使用する。 353 if( "Text".equalsIgnoreCase( readerClass ) && encode == null ) { encode = HybsSystem.sys( "FILE_ENCODE" ); } 354 readerParam.add( new AutoReaderParam( readerClass , encode , null ) ); // 8.1.2.3 (2022/05/20) 復活 355// readerParam.add( new AutoReaderParam( "Text" , encode , null ) ); // 8.1.1.0 (2022/02/04) 勘違い? 356 } 357 358 final String directory = HybsSystem.url2dir( fileURL ); 359 final File file = new File( directory,filename ); 360 // 8.0.0.2 (2021/10/15) TableReader系は、クラウドから、ローカルファイルに移してから処理する。 361 // ※ readなので、クラウドに戻す必要はない。 362 HybsFileOperationFactory.cloud2local( useLocal,() -> file ); 363 364// // 8.0.0.1 (2021/10/08) クラウド対応 365// final File file = HybsFileOperationFactory.create( directory, filename ); 366 367 final String sufix = FileInfo.getSUFIX( file ) ; // 6.2.3.0 (2015/05/01) 拡張子に応じて、チェックを変更する。 368 369 StringBuilder tempMsg = new StringBuilder( BUFFER_MIDDLE ); 370 // 6.2.5.0 (2015/06/05) AutoReaderParam 内部クラスを使用します。 371 for( final AutoReaderParam arParam : readerParam ) { 372 // 6.2.0.0 (2015/02/27) 拡張子に応じて、チェックを変更する。 373 if( !arParam.useSufix( sufix ) ) { continue; } // false:対象外の場合は、次のreaderClassを使う。 374 375 readerClass = arParam.CLASS; 376 encode = arParam.ENCODE; 377 378 // 6.4.5.1 (2016/04/28) CSV 指定時は、readerClass="Text" , separator="," に、再設定します。 379 if( "CSV".equalsIgnoreCase( readerClass ) || "CSV".equalsIgnoreCase( sufix ) ) { 380 readerClass = "Text"; 381 separator = ","; 382 } 383 384 if( isDebug() ) { 385 final String errMsg = "File=[" + file + "] , class=[" + readerClass + "] , encode=[" + encode + "]" + BR ; 386 jspPrint( errMsg ); 387 System.out.println( errMsg ); 388 } 389 390 try { 391 clmAct.isDebug = isDebug(); 392// sqlError = false; // 6.3.6.1 (2015/08/28) DirectTableInsertTag でSQLException発生時のみ処理する。 393 create( file ); // 6.2.0.0 (2015/02/27) TableReader クラスの呼び出し元メソッドの共通化(EXCEL,TEXT) 394 395 // 成功すれば、エラーメッセージをクリアして、その場で抜ける。 396 tempMsg = null; 397 break; 398 } 399 // 6.2.2.0 (2015/03/27) HybsOverflowException処理をタグ側で行う。 400 catch( final HybsOverflowException ex ) { 401 // table.setOverflow( true ); は、処理済み。ループから抜けて処理を継続する。 402 tempMsg = null; 403 break; 404 } 405 // 6.3.6.1 (2015/08/28) DirectTableInsertTag でSQLException発生時のみ処理する。 406 catch( final HybsSystemException ex ) { 407// if( sqlError ) { throw ex; } // SQLException発生時は処理中止 408 // 8.1.1.0 (2022/02/04) sqlError フラグでの判定は、DirectTableInsertTag のみで行います。 409 tempMsg.append( "File=[" ).append( file ) 410 .append( "] , Class=[" ).append( readerClass ) 411 .append( "] , Encode=[" ).append( encode ) 412 .append( "] Error!" ).append( CR ) 413 .append( ex.getMessage() ).append( CR ) ; 414 } 415 // 3.8.5.3 (2006/08/07) readerClassが "Excel"でエラーが発生したとき、もう一度Defaultで再読取を行います。 416 // 5.1.9.0 (2010/08/01) RuntimeException系のExceptionがキャッチできないため、Throwableで受ける 417 // 6.5.0.1 (2016/10/21) Throwable ではなく、OgCharacterException をキャッチして、処理を継続します。 418 catch( final OgCharacterException ex ) { 419 tempMsg.append( "File=[" ).append( file ) 420 .append( "] , Class=[" ).append( readerClass ) 421 .append( "] , Encode=[" ).append( encode ) 422 .append( "] Error!" ).append( CR ) 423 .append( ex.getMessage() ).append( CR ) ; 424 // if( isDebug() ) { 425 // jspPrint( "<pre>" + tempMsg.toString() + "</pre>" ); // 6.2.4.2 (2015/05/29) 画面にも出力します。 426 // tempMsg.append( ThrowUtil.ogStackTrace( ex ) ).append( CR ) ; // 6.4.2.0 (2016/01/29) 427 // } 428 } 429 // 7.0.5.0 (2019/09/09) OgCharacterExceptionでは、取りこぼしがあるため、OgRuntimeException も継続処理するように変更。 430 catch( final OgRuntimeException ex ) { 431 tempMsg.append( "File=[" ).append( file ) 432 .append( "] , Class=[" ).append( readerClass ) 433 .append( "] , Encode=[" ).append( encode ) 434 .append( "] Error!" ).append( CR ) 435 .append( ex.getMessage() ).append( CR ) ; 436 437 // 拡張子が、xls 以外は、処理を停止します。 438 // if( !"xls".equalsIgnoreCase( sufix ) ) { 439 // 8.1.1.0 (2022/02/04) 拡張子は、xls,xlsx 以外とする。 440 if( !"xls".equalsIgnoreCase( sufix ) || !"xlsx".equalsIgnoreCase( sufix ) ) { 441 tempMsg.append( ThrowUtil.ogStackTrace( ex ) ).append( CR ) ; 442 // break; 様子見。当面は、止めません。 443 } 444 } 445 // 6.5.0.1 (2016/10/21) Throwable をキャッチして、処理を中断します。 446 catch( final Throwable th ) { 447 tempMsg.append( "File=[" ).append( file ) 448 .append( "] , Class=[" ).append( readerClass ) 449 .append( "] , Encode=[" ).append( encode ) 450 .append( "] Error!" ).append( CR ) 451 .append( ThrowUtil.ogStackTrace( th ) ).append( CR ) ; // 6.4.2.0 (2016/01/29) 452 break; 453 } 454 } 455 456 // 6.2.3.0 (2015/05/01) 複数処理を考慮して、例外処理は発行しない。 457 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..; 458 if( tempMsg == null ) { 459 // 6.2.2.0 (2015/03/27) #afterEnd() メソッド 新規作成。 460 rtnCode = afterEnd(); 461 } 462 else { // 最後までエラーがあれば、例外処理を発行します。 463 final String errMsg = tempMsg.toString(); 464 System.err.print( errMsg ); 465 jspPrint( "<pre>" + errMsg + "</pre>" ); // 6.2.4.0 (2015/05/15) エラーを画面に出します。 466 rtnCode = SKIP_PAGE; // 6.2.4.2 (2015/05/29) エラー時はSKIP 467 } 468 } 469 470 return rtnCode ; 471 } 472 473 /** 474 * #doEndTag() の後続処理を記述します。 475 * 476 * これは、サブクラスで、DBTableModel以外の処理を行う場合に、 477 * 処理内容を分けるために用意します。 478 * 479 * @og.rev 6.2.2.0 (2015/03/27) #afterEnd() メソッド 新規作成。 480 * @og.rev 6.2.4.2 (2015/05/29) executeCount の設定がおかしい。ReadTableTagでは、設定されていなかった。 481 * @og.rev 6.2.5.0 (2015/06/05) エラー処理は、継承先でも行うので、メソッド化します。 482 * @og.rev 7.0.7.0 (2019/12/13) useSLabel 属性を追加。 483 * 484 * @return 後続処理の指示 485 */ 486 protected int afterEnd() { 487 if( table != null ) { 488 // 6.2.4.2 (2015/05/29) executeCount が設定されなくなった件 489 executeCount = table.getRowCount(); 490 491 // 3.6.0.2 (2004/10/04) 492 // 4.0.0.0 (2007/10/12) checkTableColumn 前に、modifyType 設定を行います。 493 494 // 6.2.5.0 (2015/06/05) エラー処理は、継承先でも行うので、メソッド化します。 495 final ErrorMessage errMsg = clmAct.getErrorMessage(); 496 if( !errMsg.isOK() ) { 497// jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg,getResource() ) ); 498 jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg,getResource(),useSLabel ) ); // 7.0.7.0 (2019/12/13) 499 return SKIP_PAGE ; 500 } 501 } 502 503 // 3.6.0.8 (2004/11/19) トランザクションチェックを行います。 504 if( ! commitTableObject( tableId, table ) ) { 505 jspPrint( "ReadTableTag Query処理が割り込まれました。DBTableModel は登録しません。" ); 506 return SKIP_PAGE ; 507 } 508 509 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); 510 511 // 実行件数の表示 command="NEW" のときのみ、displayMsg を表示させます。 512 // 4.0.0 (2005/11/30) 出力順の変更。一番最初に出力します。 513 if( CMD_NEW.equals( command ) ) { 514 if( executeCount > 0 && displayMsg != null && displayMsg.length() > 0 ) { 515 buf.append( executeCount ) 516 .append( getResource().getLabel( displayMsg ) ) 517 .append( BR ); 518 } 519 else if( executeCount == 0 && notfoundMsg != null && notfoundMsg.length() > 0 ) { 520 buf.append( getResource().getLabel( notfoundMsg ) ) 521 .append( BR ); 522 } 523 } 524 525 // 4.3.7.0 (2009/06/01) 読込件数を、"DB.COUNT" キーでリクエストにセットする。 526 setRequestAttribute( "DB.COUNT" , String.valueOf( executeCount ) ); 527 528 // 6.2.0.0 (2015/02/27) オーバーフロー時のメッセージを表示 529 if( table != null && table.isOverflow() && overflowMsg != null && overflowMsg.length() > 0 ) { 530 buf.append( getResource().getLabel( overflowMsg ) ) 531 .append( BR ); 532 } 533 534 jspPrint( buf.toString() ); 535 536 // 4.3.7.0 (2009/06/01) stopZero機能を追加 537 return executeCount == 0 && stopZero ? SKIP_PAGE : EVAL_PAGE ; 538 } 539 540 /** 541 * タグリブオブジェクトをリリースします。 542 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 543 * 544 * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加 545 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 546 * @og.rev 3.1.3.0 (2003/04/10) FILE_ENCODE から、エンコード情報を取得する。 547 * @og.rev 3.1.4.0 (2003/04/18) command 属性に、初期値(NEW)を設定する。 548 * @og.rev 3.5.4.2 (2003/12/15) EXCELのシート名を指定できるように変更。 549 * @og.rev 3.5.4.5 (2004/01/23) 外部よりカラム列(CSV形式)を指定できるようにする。 550 * @og.rev 3.6.0.2 (2004/10/04) checkColumns,adjustColumns,allColumnCheck 属性追加 551 * @og.rev 3.7.0.5 (2005/04/11) useNumber 属性を追加します。 552 * @og.rev 3.8.0.2 (2005/06/30) nullCheck 属性追加 553 * @og.rev 3.8.5.3 (2006/08/07) readerClass 属性の初期値をシステムリソースより取得します。 554 * @og.rev 4.3.7.0 (2009/06/01) stopZero属性追加 555 * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。 556 * @og.rev 5.1.6.0 (2010/05/01) データの読み飛ばし設定 skipRowCount 属性追加 557 * @og.rev 5.2.1.0 (2010/10/01) 読取処理でコードリソースのラベル変換を行うかどうか useRenderer 属性追加 558 * @og.rev 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるように、sheetNos属性追加 559 * @og.rev 5.5.8.2 (2012/11/09) 固定値となるカラム名、アドレスの指定のための、sheetConstKeys、sheetConstAdrs属性追加 560 * @og.rev 5.5.8.2 (2012/11/09) カラム列に NULL が現れた時点で読取を中止する、nullBreakClm属性追加 561 * @og.rev 6.1.0.0 (2014/12/26) omitNames 属性を追加 562 * @og.rev 6.2.0.0 (2015/02/27) オーバーフロー時のメッセージを表示 563 * @og.rev 6.2.0.0 (2015/02/27) EXCEL出力のparamLevel初期値変更 3:標準推奨 → 4:個人設定可 564 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。 565 * @og.rev 6.2.3.0 (2015/05/01) 行読み飛ばし nullSkipClm追加 566 * @og.rev 6.2.5.0 (2015/06/05) ファイルエンコードの初期化を遅らせます。 567 * @og.rev 7.0.7.0 (2019/12/13) useSLabel 属性を追加。 568 * @og.rev 8.0.1.0 (2021/10/29) useLocal 属性を追加。 569 */ 570 @Override 571 protected void release2() { 572 super.release2(); 573 separator = TableReader.TAB_SEPARATOR; // 項目区切り文字 574 fileURL = HybsSystem.sys( "FILE_URL" ); // ファイルURL 575 filename = HybsSystem.sys( "FILE_FILENAME" ); // ファイル名 576 encode = null; // 6.2.5.0 (2015/06/05) ファイルエンコーディング 577 readerClass = null; // 6.2.0.0 (2015/02/27) 578 maxRowCount = 0 ; // 6.2.2.0 (2015/03/27) 579 displayMsg = HybsSystem.sys( "VIEW_DISPLAY_MSG" ); 580 overflowMsg = "MSG0007"; // 検索結果が、制限行数を超えましたので、残りはカットされました。 581 notfoundMsg = "MSG0077"; // 対象データはありませんでした。 582 executeCount = -1; // 検索/実行件数 583 modifyType = null; 584 command = CMD_NEW; 585 table = null; 586 tableId = HybsSystem.TBL_MDL_KEY ; 587 sheetName = null; // 3.5.4.2 (2003/12/15) 588 sheetNos = null; // 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるようにする。 589 sheetConstKeys = null; // 5.5.8.2 (2012/11/09) 固定値となるカラム名(CSV形式) 590 sheetConstAdrs = null; // 5.5.8.2 (2012/11/09) 固定値となるアドレス(行-列,行-列,・・・) 591 nullBreakClm = null; // 5.5.8.2 (2012/11/09) 取込み条件/Sheet BREAK条件 592 nullSkipClm = null; // 6.2.3.0 (2015/05/01) 行読み飛ばし 593 columns = null; // 3.5.4.5 (2004/01/23) 594 useNumber = true; // 3.7.0.5 (2005/04/11) 595// useRepeatClms = false; // 7.3.0.0 (2021/01/06) 596 stopZero = false; // 4.3.7.0 (2009/06/01) soptZero追加 597 isMainTrans = true; // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し 598 skipRowCount = 0; // 5.1.6.0 (2010/05/01) データの読み飛ばし設定 599 clmAct = new ColumnAction(); // 6.2.2.0 (2015/03/27) 600 useSLabel = false; // 7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false) 601 useLocal = false; // 8.0.1.0 (2021/10/29) クラウド設定を使用しない場合は、true 602 } 603 604 /** 605 * TableReader の実オブジェクトを生成して,BufferedReader に書き込みます。 606 * 607 * @og.rev 3.5.4.1 (2003/12/01) 引数の BufferedReader を、InputStream に変更。 608 * @og.rev 3.5.4.2 (2003/12/15) TableReader のサブクラス名変更。 609 * @og.rev 3.5.4.2 (2003/12/15) EXCELのシート名を指定できるように変更。 610 * @og.rev 3.5.4.3 (2004/01/05) 引数の InputStream を、 BufferedReader に戻す。 611 * @og.rev 3.5.4.5 (2004/01/23) TableReader に、encode を渡すように変更。 612 * @og.rev 3.5.6.0 (2004/06/18) 各種プラグイン関連付け設定を、システムパラメータ に記述します。 613 * @og.rev 3.7.0.5 (2005/04/11) useNumber 属性を追加します。 614 * @og.rev 4.0.0.0 (2005/01/31) キーの指定を、TableReader. から、TableReader_ に変更します。 615 * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更 616 * @og.rev 5.1.6.0 (2010/05/01) データの読み飛ばし設定 skipRowCount 属性追加 617 * @og.rev 5.2.1.0 (2010/10/01) 読取処理でコードリソースのラベル変換を行うかどうか設定 useRenderer 属性追加 618 * @og.rev 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるように、sheetNos属性追加 619 * @og.rev 5.5.8.2 (2012/11/09) 固定値となるカラム名、アドレスの指定のための、sheetConstKeys、sheetConstAdrs属性追加 620 * @og.rev 5.5.8.2 (2012/11/09) カラム列に NULL が現れた時点で読取を中止する、nullBreakClm属性追加 621 * @og.rev 6.0.4.0 (2014/11/28) NullPointerException が発生するので、事前にチェックします。 622 * @og.rev 6.2.0.0 (2015/02/27) TableReader クラスの呼び出し元メソッドの共通化(EXCEL,TEXT) 623 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。 624 * @og.rev 6.2.2.0 (2015/03/27) ColumnActionListener 対応。 625 * @og.rev 6.2.3.0 (2015/05/01) 行読み飛ばし nullSkipClm追加 626 * @og.rev 6.4.1.2 (2016/01/22) setColumnActionListener は、内部処理が走るため、他の設定が終わってから呼び出す。 627 * @og.rev 6.4.3.3 (2016/03/04) HybsSystem.newInstance(String,String) への置き換え。 628 * @og.rev 7.3.0.0 (2021/01/06) ColumnActionListenerインターフェースを無名内部クラスから、内部クラスへ。 629 * @og.rev 7.3.0.0 (2021/01/06) 横持ちデータの繰り返し対応 630 * 631 * @param file 出力するFileオブジェクト 632 */ 633 protected void create( final File file ) { 634 table = DBTableModelUtil.newDBTable(); // 6.2.1.0 (2015/03/13) 635 636 final ColumnActionListener listener = new NormalCAListener(); 637 638 final TableReader reader = HybsSystem.newInstance( "TableReader_" , readerClass ); // 3.5.5.3 (2004/04/09) 639 640 reader.setSeparator( separator ); 641 reader.setColumns( columns ); // 3.5.4.5 (2004/01/23) 、6.2.0.0 (2015/02/27) 削除 642 reader.setUseNumber( useNumber ); // 3.7.0.5 (2005/04/11) 643 reader.setSkipRowCount( skipRowCount ); // 5.1.6.0 (2010/05/01) 644 reader.setDebug( isDebug() ); // 5.5.7.2 (2012/10/09) デバッグ情報を出力するかどうかを指定 645 // 6.2.0.0 (2015/02/27) EXCELでない場合でも、メソッドは呼び出す。(空振りします) 646 reader.setSheetName( sheetName ); // 3.5.4.2 (2003/12/15) 647 reader.setSheetNos( sheetNos ); // 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるようにする。 648 reader.setSheetConstData( sheetConstKeys,sheetConstAdrs ) ; // 5.5.8.2 (2012/11/09) 固定値となるカラム名、アドレスの指定 649 reader.setNullBreakClm( nullBreakClm ) ; // 5.5.8.2 (2012/11/09) 取込み条件/Sheet BREAK条件 650 reader.setNullSkipClm( nullSkipClm ) ; // 6.2.3.0 (2015/05/01) 行読み飛ばし 651 // 6.4.1.2 (2016/01/22) setColumnActionListener は、内部処理が走るため、他の設定が終わってから呼び出す。 652 reader.setColumnActionListener( listener ); // 6.2.2.0 (2015/03/27) 653 reader.readDBTable( file,encode ); // 6.2.0.0 (2015/02/27) 追加 654 } 655 656 /** 657 * ColumnActionListenerインターフェースの内部クラス 658 * 659 * @og.rev 6.2.2.0 (2015/03/27) ColumnActionListener 対応。 660 * @og.rev 7.3.0.0 (2021/01/06) ColumnActionListenerインターフェースを無名内部クラスから、内部クラスへ。 661 * @og.rev 7.3.1.1 (2021/02/25) カラム列を、"DB.NAMES" キーでリクエストにセットする。 662 * 663 * @param names カラム名配列 664 */ 665 private final class NormalCAListener implements ColumnActionListener { 666// final ColumnActionListener listener = new ColumnActionListener() { 667 private DBColumn[] dbClms ; // 6.3.9.1 (2015/11/27) 修飾子を、なし → private に変更。 668 669 /** 670 * デフォルトコンストラクター 671 * 672 * @og.rev 7.3.0.0 (2021/01/06) PMD refactoring. Each class should declare at least one constructor. 673 */ 674 public NormalCAListener() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 675 676 /** 677 * カラム名の配列が設定された場合に、呼び出されます。 678 * 679 * @og.rev 6.2.2.0 (2015/03/27) ColumnActionListener 対応。 680 * @og.rev 7.3.1.1 (2021/02/25) カラム列を、"DB.NAMES" キーでリクエストにセットする。 681 * 682 * @param names カラム名配列 683 */ 684 @Override // ColumnActionListener 685 public void columnNames( final String[] names ) { 686 final String[] nms = clmAct.makeNames( names ); 687 table.init( nms.length ); 688 dbClms = new DBColumn[nms.length]; 689 final StringBuilder nmsBuf = new StringBuilder( BUFFER_MIDDLE ); // 7.3.1.1 (2021/02/25) 690 for( int no=0; no<nms.length; no++ ) { 691 nmsBuf.append( ',' ).append( nms[no] ); // 7.3.1.1 (2021/02/25) 692 dbClms[no] = getDBColumn( nms[no] ); 693 table.setDBColumn( no,dbClms[no] ); 694 } 695 696 if( nmsBuf.length() > 1 ) { // 7.3.1.1 (2021/02/25) 最初のカンマを削除して、DB.NAMES で登録する。 697 setRequestAttribute( "DB.NAMES" , nmsBuf.substring(1) ); 698 } 699 } 700 701 /** 702 * #NAME のオリジナルカラム名配列がそろった段階で、イベントが発生します。 703 * 704 * @og.rev 7.3.1.3 (2021/03/09) #NAMEのオリジナルを取得できるようにします。 705 * 706 * @param names カラム名配列 707 */ 708 @Override // ColumnActionListener 709 public void originalNames( final String[] names ) { 710 if( names != null && names.length > 0 ) { 711 final StringBuilder nmsBuf = new StringBuilder( BUFFER_MIDDLE ); 712 for( int no=0; no<names.length; no++ ) { 713 nmsBuf.append( ',' ).append( names[no] ); 714 } 715 716 if( nmsBuf.length() > 1 ) { // 7.3.1.1 (2021/02/25) 最初のカンマを削除して、DB.NAMES で登録する。 717 setRequestAttribute( "DB.ORGNAMES" , nmsBuf.substring(1) ); 718 } 719 } 720 } 721 722 /** 723 * 1行分のデータが設定された場合に、呼び出されます。 724 * 725 * @og.rev 6.2.2.0 (2015/03/27) ColumnActionListener 対応。 726 * @og.rev 6.4.6.0 (2016/05/27) レコードの読取条件指定を追加。条件に一致しなければ、null が返されます。 727 * @og.rev 7.3.0.0 (2021/01/06) 横持ちデータの繰り返し対応 728 * @og.rev 8.4.0.0 (2022/12/23) 7.1.0.0 (2020/01/27) の対応は、ReadTableTag に移動。 729 * 730 * @param vals 文字列値の1行分の配列 731 * @param rowNo 行番号(0~) 732 */ 733 @Override // ColumnActionListener 734 public void values( final String[] vals, final int rowNo ) { 735 if( maxRowCount > 0 && rowNo > maxRowCount ) { // 読み取り件数オーバーフロー 736 table.setOverflow( true ); 737 throw new HybsOverflowException(); 738 } 739 740 // 7.3.0.0 (2021/01/06) 横持ちデータの繰り返し対応。 741// final String[] newVals = clmAct.clmAction( vals , dbClms , rowNo ); 742// // 6.4.6.0 (2016/05/27) レコードの読取条件指定を追加。条件に一致しなければ、null が返されます。 743// if( newVals != null ) { 744// table.addColumnValues( newVals,modifyType,true ); // 値配列、変更タイプ、書込許可 745// } 746 final List<String[]> valsList = clmAct.clmAction( vals , dbClms , rowNo ); 747 if( valsList != null ) { // 8.4.0.0 (2022/12/23) nullチェック漏れ 748 for( final String[] newVals : valsList ) { 749 // 8.4.0.0 (2022/12/23) セパレータ分割時にデータ分割されない場合は、エンコードエラーの可能性が高い 750 // 7.1.0.0 (2020/01/27) で、fukurou.model.TableModelHelper#value の処理を移植 751 if( table.getColumnCount() > 1 && newVals.length == 1 ) { 752 final String errMsg = "カラム数とデータ数が合いません。エンコードエラーの可能性があります。"; 753 throw new OgCharacterException( errMsg ); 754 } 755 table.addColumnValues( newVals,modifyType,true ); // 値配列、変更タイプ、書込許可 756 } 757 } 758 } 759 760 /** 761 * 新しくEXCELのシートを処理する際に、シート名をセットするときに呼び出されます。 762 * 763 * @og.rev 7.3.1.1 (2021/02/25) 現在実行中のシート名を、"DB.SHEET_NAME" キーでリクエストにセットする。 764 * 765 * @param sheetName 現在実行中のシート名 766 */ 767 @Override // ColumnActionListener 768 public void shtName( final String sheetName ) { 769 setRequestAttribute( "DB.SHEET_NAME" , sheetName ); 770 } 771 } 772 773 /** 774 * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します 775 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。 776 * 777 * @og.tag 778 * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に 779 * 渡す場合に、通常は、session を利用します。その場合の登録キーです。 780 * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、 781 * この tableId 属性を利用して、メモリ空間を分けます。 782 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。 783 * 784 * @param id テーブルID (sessionに登録する時のID) 785 */ 786 public void setTableId( final String id ) { 787 tableId = nval( getRequestParameter( id ), tableId ); 788 } 789 790 /** 791 * 【TAG】可変長ファイルを作成するときの項目区切り文字をセットします。 792 * 793 * @og.tag 可変長ファイルを作成するときの項目区切り文字をセットします。 794 * 795 * @param separator 項目区切り文字 796 */ 797 public void setSeparator( final String separator ) { 798 this.separator = nval( getRequestParameter( separator ),this.separator ); 799 } 800 801 /** 802 * 【TAG】読取元ディレクトリ名を指定します 803 * (初期値:FILE_URL[={@og.value SystemData#FILE_URL}])。 804 * 805 * @og.tag 806 * この属性で指定されるディレクトリより、ファイルを読取ます。 807 * 指定方法は、通常の fileURL 属性と同様に、先頭が、'/' (UNIX) または、2文字目が、 808 * ":" (Windows)の場合は、指定のURLそのままのディレクトリに、そうでない場合は、 809 * fileURL = "{@USER.ID}" と指定すると、FILE_URL 属性で指定のフォルダの下に、 810 * さらに、各個人ID別のフォルダを作成して、そこを操作します。 811 * (初期値:システム定数のFILE_URL[={@og.value SystemData#FILE_URL}])。 812 * 813 * @og.rev 4.0.0.0 (2005/01/31) StringUtil.urlAppend メソッドの利用 814 * @og.rev 4.0.0.0 (2007/11/20) 指定されたディレクトリ名の最後が"\"or"/"で終わっていない場合に、"/"を付加する。 815 * @og.rev 6.4.2.1 (2016/02/05) URLの最後に、"/" を追加する処理を廃止。 816 * 817 * @param url 読取元ディレクトリ名 818 * @see org.opengion.hayabusa.common.SystemData#FILE_URL 819 */ 820 public void setFileURL( final String url ) { 821 final String furl = nval( getRequestParameter( url ),null ); 822 if( furl != null ) { 823 fileURL = StringUtil.urlAppend( fileURL,furl ); 824 } 825 } 826 827 /** 828 * 【TAG】ファイルを作成するときのファイル名をセットします 829 * (初期値:FILE_FILENAME[={@og.value SystemData#FILE_FILENAME}])。 830 * 831 * @og.tag ファイルを作成するときのファイル名をセットします。 832 * (初期値:システム定数のFILE_FILENAME[={@og.value SystemData#FILE_FILENAME}])。 833 * 834 * @param filename ファイル名 835 * @see org.opengion.hayabusa.common.SystemData#USE_SQL_INJECTION_CHECK 836 */ 837 public void setFilename( final String filename ) { 838 this.filename = nval( getRequestParameter( filename ),this.filename ); 839 } 840 841 /** 842 * 【TAG】ファイルを作成するときのファイルエンコーディング名をセットします 843 * (初期値:FILE_ENCODE[={@og.value SystemData#FILE_ENCODE}])。 844 * 845 * @og.tag 846 * readerClass="AutoReader" の場合、ここで設定した encode が優先されます。 847 * readerClass="Text" の場合、encode が指定されていない場合は、初期値 の FILE_ENCODE が使用されます 848 * 849 * Shift_JIS,MS932,Windows-31J,UTF-8,ISO-8859-1,UnicodeLittle 850 * (初期値:システム定数のFILE_ENCODE[={@og.value SystemData#FILE_ENCODE}])。 851 * 852 * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更 853 * @og.rev 3.1.3.0 (2003/04/10) FILE_ENCODE から、エンコード情報を取得する。 854 * 855 * @param enc ファイルエンコーディング名 856 * @see <a href="http://www.iana.org/assignments/character-sets" target="_blank" >IANA Charset Registry</a> 857 * @see org.opengion.hayabusa.common.SystemData#FILE_ENCODE 858 */ 859 public void setEncode( final String enc ) { 860 encode = nval( getRequestParameter( enc ),encode ); 861 } 862 863 /** 864 * 【TAG】実際に読み出すクラス名の略称(TableReader_**** の ****)をセットします 865 * (初期値:TABLE_READER_DEFAULT_CLASS[={@og.value SystemData#TABLE_READER_DEFAULT_CLASS}])。 866 * 867 * @og.tag 868 * 実際に読み出すクラス名(の略称)をセットします。 869 * これは、org.opengion.hayabusa.io 以下の TableReader_**** クラスの **** を 870 * 与えます。これらは、TableReader インターフェースを継承したサブクラスです。 871 * 属性クラス定義の {@link org.opengion.hayabusa.io.TableReader TableReader} を参照願います。 872 * {@og.doc03Link readerClass TableReader_**** クラス} 873 * @og.rev 3.1.3.0 (2003/04/10) FILE_ENCODE から、エンコード情報を取得する。 874 * 875 * "AutoReader" は特別な名前で、Excel と Text(テキスト) を以下の順番で試します。 876 * Excel,Calc,Text(UnicodeLittle),Text(Windows-31J),Text(Windows-31J),Text(UTF-8),Text(EUC-JP) 877 * Excel については、拡張子を自動判定して、(xlsx か xls) 適切な処理を行います。 878 * 従来からの 拡張子のみ、xls のテキストファイルは、#NAME を見つけることができないため、エラーになり、 879 * 次のText読み取りにゆだねられます。 880 * UTF-8 のTEXTとWindows-31JのTEXTは、ヘッダー部での区別ができないため、java.nio.file.Files と Pathを 881 * 使用した読み取り方式に変更しています。 882 * "AutoReader" に設定した場合は、上記の様に、encode を順番に確かめるため、encode属性の指定は無視されます。 883 * (初期値:TABLE_READER_DEFAULT_CLASS[={@og.value SystemData#TABLE_READER_DEFAULT_CLASS}])。 884 * 885 * @og.rev 6.2.1.0 (2015/03/13) Default廃止に伴い、Defaultが指定された場合は、Textに置き換える。 886 * 887 * @param readerCls クラス名(の略称) 888 * @see org.opengion.hayabusa.io.TableReader TableReaderのサブクラス 889 */ 890 public void setReaderClass( final String readerCls ) { 891 readerClass = nval( getRequestParameter( readerCls ),readerClass ); 892 893 // 6.2.1.0 (2015/03/13) 互換性の為。 894 if( "Default".equals( readerClass ) ) { readerClass = "Text" ; } 895 } 896 897 /** 898 * 【TAG】読取時の最大取込件数をセットします(初期値:0:無制限)。 899 * 900 * @og.tag 901 * DBTableModelのデータとして登録する最大件数をこの値に設定します。 902 * サーバーのメモリ資源と応答時間の確保の為です。 903 * 0 をセットすると、無制限になります。 904 * (初期値:0:無制限) 905 * 906 * @og.rev 5.5.8.5 (2012/11/27) 0を無制限として処理します。 907 * @og.rev 6.2.2.0 (2015/03/27) 初期値を、無制限に変更 908 * 909 * @param count 最大件数 910 */ 911 public void setMaxRowCount( final String count ) { 912 maxRowCount = nval( getRequestParameter( count ),maxRowCount ); 913 } 914 915 /** 916 * 【TAG】読取時の最大エラー件数をセットします (初期値:{@og.value #ERROR_ROW_COUNT})。 917 * 918 * @og.tag 919 * DBTableModelのデータチェックを行う場合、エラーの最大件数をこの値に設定します。 920 * エラー最大件数がこの値を超えると、処理を打ち切ります。 921 * 0 をセットすると、無制限になります。 922 * (初期値:{@og.value #ERROR_ROW_COUNT})。 923 * 924 * @og.rev 6.2.2.0 (2015/03/27) 読取時の最大エラー件数(errRowCount) を新規追加 925 * 926 * @param count 最大件数 927 */ 928 public void setErrRowCount( final String count ) { 929 clmAct.errRowCount = nval( getRequestParameter( count ),ERROR_ROW_COUNT ); 930 } 931 932 /** 933 * 【TAG】コマンド (NEW,RENEW)をセットします(初期値:NEW)。 934 * 935 * @og.tag 936 * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される 937 * フィールド定数値のいづれかを、指定できます。 938 * 何も設定されない、または、null の場合は、"NEW" が初期値にセットされます。 939 * 940 * @param cmd コマンド (public static final 宣言されている文字列) 941 * @see <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.ReadTableTag.CMD_NEW">コマンド定数</a> 942 */ 943 public void setCommand( final String cmd ) { 944 final String cmd2 = getRequestParameter( cmd ); 945 if( cmd2 != null && cmd2.length() > 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); } 946 } 947 948 /** 949 * 【TAG】query の結果を画面上に表示するメッセージIDを指定します 950 * (初期値:VIEW_DISPLAY_MSG[={@og.value SystemData#VIEW_DISPLAY_MSG}])。 951 * 952 * @og.tag 953 * ここでは、検索結果の件数や登録された件数をまず出力し、 954 * その次に、ここで指定したメッセージをリソースから取得して 955 * 表示します。 956 * 件数を表示させる場合は、displayMsg = "MSG0033"[ 件検索しました] をセットしてください。 957 * 表示させたくない場合は, displayMsg = "" をセットしてください。 958 * (初期値:システム定数のVIEW_DISPLAY_MSG[={@og.value SystemData#VIEW_DISPLAY_MSG}])。 959 * 960 * @og.rev 6.2.0.0 (2015/02/27) リクエスト変数を使用できるように修正。 961 * 962 * @param id 処理結果表示メッセージID 963 */ 964 public void setDisplayMsg( final String id ) { 965 final String ids = getRequestParameter( id ); 966 if( ids != null ) { displayMsg = ids; } 967 } 968 969 /** 970 * 【TAG】読取データが最大検索数をオーバーした場合に表示するメッセージリソースIDを指定します 971 * (初期値:MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました])。 972 * 973 * @og.tag 974 * 読取結果が、maxRowCount で設定された値より多い場合、何らかのデータは読取されず 975 * 切り捨てられたことになります。 976 * ここでは、displayMsg を表示した後、必要に応じて、このメッセージを表示します。 977 * 表示させたくない場合は, overflowMsg = "" をセットしてください。 978 * 初期値は、MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました]です。 979 * 980 * @og.rev 6.2.0.0 (2015/02/27) オーバーフロー時のメッセージを表示 981 * 982 * @param id 検索数オーバー時メッセージID 983 */ 984 public void setOverflowMsg( final String id ) { 985 final String ids = getRequestParameter( id ); 986 if( ids != null ) { overflowMsg = ids; } 987 } 988 989 /** 990 * 【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした])。 991 * 992 * @og.tag 993 * ここでは、検索結果がゼロ件の場合のみ、特別なメッセージを表示させます。 994 * 従来は、displayMsg と兼用で、『0 件検索しました』という表示でしたが、 995 * displayMsg の初期表示は、OFF になりましたので、ゼロ件の場合のみ別に表示させます。 996 * 表示させたくない場合は, notfoundMsg = "" をセットしてください。 997 * 初期値は、MSG0077[対象データはありませんでした]です。 998 * 999 * @param id ゼロ件時表示メッセージID 1000 */ 1001 public void setNotfoundMsg( final String id ) { 1002 final String ids = getRequestParameter( id ); 1003 if( ids != null ) { notfoundMsg = ids; } 1004 } 1005 1006 /** 1007 * 【TAG】ファイル取込時の 更新タイプ [A:追加/C:更新/D:削除]を指定します。 1008 * 1009 * @og.tag 1010 * ファイル読み込み時に、そのデータをA(追加)、C(更新)、D(削除)の 1011 * 更新タイプをつけた状態にします。 1012 * その状態で、そのまま、update する事が可能になります。 1013 * 1014 * @param type 更新タイプ [A:追加/C:更新/D:削除] 1015 */ 1016 public void setModifyType( final String type ) { 1017 modifyType = getRequestParameter( type ); 1018 } 1019 1020 /** 1021 * 【TAG】EXCELファイルを読み込むときのシート名を設定します(初期値:指定なし)。 1022 * 1023 * @og.tag 1024 * EXCELファイルを読み込む時に、シート名を指定します。これにより、複数の形式の 1025 * 異なるデータを順次読み込むことや、シートを指定して読み取ることが可能になります。 1026 * sheetNos と sheetName が同時に指定された場合は、sheetNos が優先されます。エラーにはならないのでご注意ください。 1027 * 初期値は、指定なしです。 1028 * 1029 * @og.rev 3.5.4.2 (2003/12/15) 新規追加 1030 * 1031 * @param sheet EXCELファイルのシート名 1032 * @see #setSheetNos( String ) 1033 */ 1034 public void setSheetName( final String sheet ) { 1035 sheetName = nval( getRequestParameter( sheet ),sheetName ); 1036 } 1037 1038 /** 1039 * 【TAG】EXCELファイルを読み込むときのシート番号を指定します(初期値:0)。 1040 * 1041 * @og.tag 1042 * EXCEL読み込み時に複数シートをマージして取込ます。 1043 * シート番号は、0 から始まる数字で表します。 1044 * ヘッダーは、最初のシートのカラム位置に合わせます。(ヘッダータイトルの自動認識はありません。) 1045 * よって、指定するシートは、すべて同一レイアウトでないと取込時にカラムのずれが発生します。 1046 * 1047 * シート番号の指定は、CSV形式で、複数指定できます。また、N-M の様にハイフンで繋げることで、 1048 * N 番から、M 番のシート範囲を一括指定可能です。また、"*" による、全シート指定が可能です。 1049 * これらの組み合わせも可能です。( 0,1,3,5-8,10-* ) 1050 * ただし、"*" に関しては例外的に、一文字だけで、すべてのシートを表すか、N-* を最後に指定するかの 1051 * どちらかです。途中には、"*" は、現れません。 1052 * シート番号は、重複(1,1,2,2)、逆転(3,2,1) での指定が可能です。これは、その指定順で、読み込まれます。 1053 * sheetNos と sheetName が同時に指定された場合は、sheetNos が優先されます。エラーにはならないのでご注意ください。 1054 * 1055 * 初期値は、0(第一シート) です。 1056 * 1057 * @og.rev 5.5.7.2 (2012/10/09) 新規追加 1058 * 1059 * @param sheet EXCELファイルのシート番号(0から始まる) 1060 * @see #setSheetName( String ) 1061 */ 1062 public void setSheetNos( final String sheet ) { 1063 sheetNos = nval( getRequestParameter( sheet ),sheetNos ); 1064 if( sheetNos != null && sheetNos.length() > 0 ) { 1065 boolean errFlag = false; 1066 for( int i=0; i<sheetNos.length(); i++ ) { 1067 final char ch = sheetNos.charAt(i); 1068 if( ch == '-' || ch == ',' ) { continue; } 1069 if( ch == '*' && ( i==0 || i==sheetNos.length()-1 ) ) { continue; } 1070 if( ch < '0' || ch > '9' ) { errFlag = true; break; } 1071 } 1072 if( errFlag ) { 1073 final String errMsg = "sheetNos の指定を見直してください。sheetNos=[" + sheetNos + "]"; 1074 throw new HybsSystemException( errMsg ); 1075 } 1076 } 1077 } 1078 1079 /** 1080 * 【TAG】EXCELファイルを読み込むときのシート単位の固定値を設定するためのカラム名を指定します。 1081 * 1082 * @og.tag 1083 * カラム名は、CSV形式で指定します。 1084 * これにより、シートの一か所に書かれている情報を、DBTableModel のカラムに固定値として 1085 * 設定することができます。 1086 * 例として、DB定義書で、テーブル名をシートの全レコードに設定したい場合などに使います。 1087 * このメソッドは、isExcel() == true の場合のみ利用されます。 1088 * 1089 * @og.rev 5.5.8.2 (2012/11/09) 新規追加 1090 * 1091 * @param constKeys 固定値となるカラム名 (CSV形式) 1092 * @see #setSheetConstAdrs( String ) 1093 */ 1094 public void setSheetConstKeys( final String constKeys ) { 1095 sheetConstKeys = nval( getRequestParameter( constKeys ),null ); 1096 } 1097 1098 /** 1099 * 【TAG】EXCELファイルを読み込むときのシート単位の固定値を設定するためのカラム名に対応するアドレスを指定します。 1100 * 1101 * @og.tag 1102 * アドレスは、EXCEL上の行-列をCSV形式で指定します。 1103 * 行列は、EXCELオブジェクトに準拠するため、0から始まる整数です。 1104 * 0-0 ⇒ A1 , 1-0 ⇒ A2 , 0-1 ⇒ B1 になります。 1105 * これにより、シートの一か所に書かれている情報を、DBTableModel のカラムに固定値として 1106 * 設定することができます。 1107 * 例として、DB定義書で、テーブル名をシートの全レコードに設定したい場合などに使います。 1108 * このメソッドは、isExcel() == true の場合のみ利用されます。 1109 * 1110 * 5.7.6.3 (2014/05/23) より、 1111 * ①EXCEL表記に準拠した、A1,A2,B1 の記述も処理できるように対応します。 1112 * なお、A1,A2,B1 の記述は、必ず、英字1文字+数字 にしてください。(A~Zまで) 1113 * ②処理中のEXCELシート名をカラムに割り当てるために、"SHEET" という記号に対応します。 1114 * 例えば、sheetConstKeys="CLM,LANG,NAME" とし、sheetConstAdrs="0-0,A2,SHEET" とすると、 1115 * NAMEカラムには、シート名を読み込むことができます。 1116 * これは、内部処理の簡素化のためです。 1117 * 1118 * ちなみに、EXCELのセルに、シート名を表示させる場合の関数は、下記の様になります。 1119 * =RIGHT(CELL("filename",$A$1),LEN(CELL("filename",$A$1))-FIND("]",CELL("filename",$A$1))) 1120 * 1121 * @og.rev 5.5.8.2 (2012/11/09) 新規追加 1122 * 1123 * @param constAdrs 固定値となるアドレス (行-列,行-列,・・・) 1124 * @see #setSheetConstKeys( String ) 1125 */ 1126 public void setSheetConstAdrs( final String constAdrs ) { 1127 sheetConstAdrs = nval( getRequestParameter( constAdrs ),null ); 1128 } 1129 1130 /** 1131 * 【TAG】ここに指定されたカラム列に NULL が現れた時点で読取を中止します。 1132 * 1133 * @og.tag 1134 * これは、指定のカラムは必須という事を条件に、そのレコードだけを読み取る処理を行います。 1135 * 複数Sheetの場合は、次のSheetを読みます。 1136 * 現時点では、Excel の場合のみ有効です。 1137 * 1138 * @og.rev 5.5.8.2 (2012/11/09) 新規追加 1139 * 1140 * @param clm カラム列 1141 */ 1142 public void setNullBreakClm( final String clm ) { 1143 nullBreakClm = nval( getRequestParameter( clm ),null ); 1144 } 1145 1146 /** 1147 * 【TAG】ここに指定されたカラム列に NULL が現れたレコードは読み飛ばします。 1148 * 1149 * @og.tag 1150 * 例えば、更新対象カラムで、null の場合は、何もしない、などのケースで使用できます。 1151 * 複数カラムの場合は、AND条件やOR条件などが、考えられるため、 1152 * カラムを一つにまとめて、指定してください。 1153 * 1154 * @og.rev 6.2.3.0 (2015/05/01) 行読み飛ばし nullSkipClm追加 1155 * 1156 * @param clm カラム列 1157 */ 1158 public void setNullSkipClm( final String clm ) { 1159 nullSkipClm = nval( getRequestParameter( clm ),null ); 1160 } 1161 1162 /** 1163 * 【TAG】読取元ファイルのカラム列を、外部(タグ)より指定します。 1164 * 1165 * @og.tag 1166 * 読取元ファイルのカラム列を、外部(タグ)より指定します。 1167 * ファイルに記述された #NAME より優先して使用されます。 1168 * これは、元ファイルのカラムを順番に指定のカラム名に割り当てる機能で 1169 * ファイルの特定のカラム列を抜き出して取り込む機能ではありません。 1170 * 1171 * ※ 7.2.6.0 (2020/06/30) 1172 * readerClass="POI"の場合、TEXT(テキスト)、CMNT(コメント)の位置は変えられません。 1173 * また、カラム数も、必ず、2以上必要です。 1174 * それより多い場合は、null値のカラムが作成されます。 1175 * 1176 * @og.rev 3.5.4.5 (2004/01/23) 新規作成 1177 * 1178 * @param clms 読取元ファイルのカラム列 (CSV形式) 1179 */ 1180 public void setColumns( final String clms ) { 1181 columns = nval( getRequestParameter( clms ),columns ); 1182 } 1183 1184 /** 1185 * 【TAG】読取対象外のカラム列を、外部(タグ)よりCSV形式で指定します。 1186 * 1187 * @og.tag 1188 * 指定するカラム名に対して、読取処理を行いません。 1189 * ここで指定するカラム名は、ファイルの #NAME または、columns で 1190 * 指定するカラム名に対して、含まれている必要はありません。 1191 * その場合は、ここでの指定は無視されます。 1192 * 1193 * @og.rev 6.1.0.0 (2014/12/26) omitNames 属性を追加 1194 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。 1195 * 1196 * @param clms 読取対象外のカラム列 (CSV形式) 1197 */ 1198 public void setOmitNames( final String clms ) { 1199 clmAct.omitNames = nval( getRequestParameter( clms ),null ); 1200 } 1201 1202 /** 1203 * 読取対象外のカラム列を、追加指定します。 1204 * 1205 * 内部的な処理で、DirectTableInsertTag で、WRITABLE,ROWID などの 1206 * データベースに存在しないカラムを、omit するための機能です。 1207 * 属性定義してもよいのですが、統一的な処理方法が決まらないので、 1208 * 取りあえず、暫定的に、サブクラスからのみ、して可能にしておきます。 1209 * このメソッドは、setOmitNames( String ) が呼び出された後でしか 1210 * 有効に機能しません。 1211 * 1212 * @og.rev 6.2.4.0 (2015/05/15) 無条件でOMITする名称を指定します。 1213 * 1214 * @param omit 読取対象外の追加カラム列 (CSV形式) 1215 */ 1216 protected void addOmitNames( final String omit ) { 1217 if( clmAct.omitNames == null ) { 1218 clmAct.omitNames = omit; 1219 } 1220 else { 1221 clmAct.omitNames = "," + omit ; 1222 } 1223 } 1224 1225 /** 1226 * 【TAG】読取元ファイルの整合性チェックを行うカラム列をカンマ指定します。 1227 * 1228 * @og.tag 1229 * カラムオブジェクトのDBType属性に対応したチェックを行います。 1230 * 指定のカラム名をCSV形式(CSV)で複数指定できます。 1231 * 全てのカラムのチェックを行う場合は、"*" を指定して下さい。 1232 * 分解方法は、通常のパラメータ取得後に、CSV分解します。 1233 * 1234 * @og.rev 3.6.0.2 (2004/10/04) 新規追加 取込時チェック用 1235 * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。 1236 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。 1237 * 1238 * @param clms 整合性チェックを行うカラム列 (CSV形式) 1239 */ 1240 public void setCheckColumns( final String clms ) { 1241 clmAct.checkColumns = nval( getRequestParameter( clms ),null ); 1242 } 1243 1244 /** 1245 * 【TAG】整合性チェック時に、厳密にチェックするかどうか[true/false]を指定します(初期値:true)。 1246 * 1247 * @og.tag 1248 * checkColumnsで、読取元ファイルの整合性チェックを行う際に、厳密なチェックを行うかどうかを指定します。 1249 * 従来は、厳密なチェックのみでしたが、動的に作成したカラムで、DB登録に無関係な場合は、 1250 * official(カラムリソースから作成されたかどうか)が」falseになり、必ずエラーになっていました。 1251 * isStrict=false を指定すると、甘い目でカラムチェックすると同時に、official チェックも行いません。 1252 * 初期値は、互換性を考慮して、true になります。 1253 * 1254 * @og.rev 7.3.2.0 (2021/03/19) isStrict:整合性チェック時に、厳密にチェックするかどうか[true/false]追加(初期値:true) 1255 * 1256 * @param flag 厳密チェックか [true:厳密/false:甘い] 1257 */ 1258 public void setUseStrict( final String flag ) { 1259 clmAct.isStrict = nval( getRequestParameter( flag ),clmAct.isStrict ); 1260 } 1261 1262 /** 1263 * 【TAG】読取元ファイルのデータ変換を行うカラム列をカンマ指定します。 1264 * 1265 * @og.tag 1266 * カラムオブジェクトのDBType属性に対応したデータ変換を行います。 1267 * 指定のカラム名をCSV形式(CSV)で複数指定できます。 1268 * 全てのカラムをデータ変換する場合は、"*" を指定して下さい。 1269 * 分解方法は、通常のパラメータ取得後に、CSV分解します。 1270 * 1271 * @og.rev 3.6.0.2 (2004/10/04) 新規追加 取込時データ変換 1272 * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。 1273 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。 1274 * 1275 * @param clms データ変換を行うカラム列 (CSV形式) 1276 */ 1277 public void setAdjustColumns( final String clms ) { 1278 clmAct.adjustColumns = nval( getRequestParameter( clms ),null ); 1279 } 1280 1281 /** 1282 * 【TAG】NULL チェックすべきカラム列をCSV形式(CSV形式)で指定します。 1283 * 1284 * @og.tag nullCheck="AAA,BBB,CCC,DDD" 1285 * 分解方法は、通常のパラメータ取得後に、CSV分解します。 1286 * 1287 * @og.rev 3.8.0.2 (2005/06/30) 新規追加 1288 * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。 1289 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。 1290 * 1291 * @param clms カラム列(CSV形式) 1292 */ 1293 public void setNullCheck( final String clms ) { 1294 clmAct.nullCheck = nval( getRequestParameter( clms ),null ); 1295 } 1296 1297 /** 1298 * 【TAG】行番号情報を、使用している/していない[true/false]を指定します(初期値:true)。 1299 * 1300 * @og.tag 1301 * 通常のフォーマットでは、各行の先頭に行番号が出力されています。 1302 * 読取時に、#NAME 属性を使用する場合は、この行番号を無視しています。 1303 * #NAME 属性を使用せず、columns 属性でカラム名を指定する場合(他システムの 1304 * 出力ファイルを読み取るケース等)では、行番号も存在しないケースがあり、 1305 * その様な場合に、useNumber="false" を指定すれば、データの最初から読取始めます。 1306 * この場合、出力データのカラムの並び順が変更された場合、columns 属性も 1307 * 指定しなおす必要がありますので、できるだけ、#NAME 属性を使用するように 1308 * してください。 1309 * なお、EXCEL 入力には、この設定は適用されません。(暫定対応) 1310 * 初期値は、true(使用する) です。 1311 * 1312 * @og.rev 3.7.0.5 (2005/04/11) 新規追加 1313 * 1314 * @param useNo 行番号情報 [true:使用する/false:使用しない] 1315 */ 1316 public void setUseNumber( final String useNo ) { 1317 useNumber = nval( getRequestParameter( useNo ),useNumber ); 1318 } 1319 1320 /** 1321 * 【TAG】読取処理で横持ちデータの繰り返しが存在する場合に、trueを指定します(初期値:false)。 1322 * 1323 * @og.tag 1324 * データを取り込む際、1行に繰り返しカラムが存在する場合に、true に設定します。 1325 * 例えば、注文番号,品番,納期1,数量1,納期2,数量2…納期31,数量31,備考 のようなデータ形式です。 1326 * これを、 1327 * 注文番号,品番,備考,納期1,数量1 1328 * 注文番号,品番,備考,納期2,数量2 1329 * ・・・ 1330 * 注文番号,品番,備考,納期31,数量31 1331 * のように、縦型のデータに変更します。 1332 * 1333 * 繰り返しカラムの廃位を [] で囲います。先の例でいうと、 1334 * 注文番号,品番,[納期1,数量1],[納期2,数量2]…[納期31,数量31],備考 になります。 1335 * 1336 * 従来の取込と同じく、カラムが空欄(,,,,などと指定)の場合は、読み飛ばします。 1337 * なお、[] で囲われていないカラムは、固定カラムで、繰り返しカラムより前に来ます。 1338 * 先の例でいうと、備考は、品番の次に来ます。 1339 * 繰り返しカラムの指定は、1度だけできます。複数の繰り返しカラムには対応していません。 1340 * 初期値は、false(使用しない) です。 1341 * 1342 * @og.rev 7.3.0.0 (2021/01/06) 横持ちデータの繰り返し対応。 1343 * 1344 * @param useRepeat 横持ちデータの繰り返し [true:使用する/false:使用しない] 1345 */ 1346 public void setUseRepeatClms( final String useRepeat ) { 1347// useRepeatClms = nval( getRequestParameter( useRepeat ),useRepeatClms ); 1348 clmAct.useRepeatClms( nval( getRequestParameter( useRepeat ),false ) ); 1349 } 1350 1351 /** 1352 * 【TAG】読込件数が0件のとき処理を続行するかどうか[true/false]を指定します(初期値:false[続行する])。 1353 * 1354 * @og.tag 1355 * 初期値は、false(続行する)です。 1356 * 1357 * @og.rev 4.3.7.0 (2009/06/01) 新規追加 1358 * 1359 * @param flag 0件時停止可否 [true:処理を中止する/false:続行する] 1360 */ 1361 public void setStopZero( final String flag ) { 1362 stopZero = nval( getRequestParameter( flag ), stopZero ); 1363 } 1364 1365 /** 1366 * 【TAG】(通常は使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:true)。 1367 * 1368 * @og.tag 1369 * この値は、ファイルダウンロード処理に影響します。この値がtrueに指定された時にcommitされたDBTableModelが 1370 * ファイルダウンロードの対象の表になります。 1371 * 1372 * このパラメーターは、通常、各タグにより実装され、ユーザーが指定する必要はありません。 1373 * 但し、1つのJSP内でDBTableModelが複数生成される場合に、前に処理したDBTableModelについてファイルダウンロードをさせたい 1374 * 場合は、後ろでDBTableModelを生成するタグで、明示的にこの値をfalseに指定することで、ファイルダウンロード処理の対象から 1375 * 除外することができます。 1376 * 1377 * @og.rev 5.1.6.0 (2010/05/01) 新規作成 1378 * 1379 * @param flag メイントランザクションかどうか [true:メイン/false:その他] 1380 */ 1381 public void setMainTrans( final String flag ) { 1382 isMainTrans = nval( getRequestParameter( flag ),isMainTrans ); 1383 } 1384 1385 /** 1386 * 【TAG】(通常は使いません)データの読み飛ばし件数を設定します。 1387 * 1388 * @og.tag 1389 * TAB区切りテキストやEXCEL等のデータの読み始めの初期値を指定します。 1390 * ファイルの先頭行が、0行としてカウントしますので、設定値は、読み飛ばす 1391 * 件数になります。(1と指定すると、1件読み飛ばし、2行目から読み込みます。) 1392 * 読み飛ばしは、コメント行などは、無視しますので、実際の行数分読み飛ばします。 1393 * #NAME属性や、columns 属性は、有効です。 1394 * 1395 * @og.rev 5.1.6.0 (2010/05/01) 新規作成 1396 * 1397 * @param count 読み始めの初期値 1398 */ 1399 public void setSkipRowCount( final String count ) { 1400 skipRowCount = nval( getRequestParameter( count ),skipRowCount ); 1401 } 1402 1403 /** 1404 * 【TAG】読取処理でKEY:VAL形式のコードリソースから、KEYを取り出す処理を行うかどうかを指定します 1405 * (初期値:USE_TABLE_READER_RENDERER[={@og.value SystemData#USE_TABLE_READER_RENDERER}])。 1406 * 1407 * @og.tag 1408 * TableWriter_Renderer 系のクラスで出力した場合は、コードリソースがラベルで出力されます。 1409 * そのファイルを読み取ると、当然、エラーになります。 1410 * ここでは、コードリソースのカラムに対して、ラベルからコードを求める逆変換を行うことで、 1411 * Renderer 系で出力したファイルを取り込むことができるようにします。 1412 * 1413 * ここでは、TableWriter 系と同様に、TableReader_Renderer 系のクラスを作るのではなく、 1414 * 属性値のフラグで、制御します。 1415 * 将来的には、TableWriter 系も廃止して、同様のフラグで制御するように変更する予定です。 1416 * (初期値:システム定数のUSE_TABLE_READER_RENDERER[={@og.value SystemData#USE_TABLE_READER_RENDERER}])。 1417 * 1418 * @og.rev 5.2.1.0 (2010/10/01) 新規作成 1419 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。 1420 * 1421 * @param flag ラベル逆変換を行うかどうか [true:行う/false:行わない] 1422 * @see org.opengion.hayabusa.common.SystemData#USE_TABLE_READER_RENDERER 1423 */ 1424 public void setUseRenderer( final String flag ) { 1425 clmAct.useRenderer = nval( getRequestParameter( flag ),HybsSystem.sysBool( "USE_TABLE_READER_RENDERER" ) ); 1426 } 1427 1428 /** 1429 * 【TAG】matchKeysをCSV形式で指定します。 1430 * 1431 * @og.tag 1432 * ファイルから特定の行のみを読み取るためのmatchKeysを指定します。 1433 * matchKeysで指定したカラムに対して、matchValsの正規表現でチェックします。 1434 * 何も指定しない場合は、読取対象になります。 1435 * matchVals と個数を合わせてください。 1436 * 1437 * @og.rev 6.4.6.0 (2016/05/27) 新規追加 1438 * 1439 * @param keys カラム列(CSV形式文字) 1440 * @see #setMatchVals( String ) 1441 */ 1442 public void setMatchKeys( final String keys ) { 1443 clmAct.matchKeys = getCSVParameter( keys ); 1444 } 1445 1446 /** 1447 * 【TAG】matchValsをCSV形式で指定します。 1448 * 1449 * @og.tag 1450 * ファイルから特定の行のみを読み取るためのmatchValsを指定します。 1451 * matchKeysで指定したカラムに対して、matchValsの正規表現でチェックします。 1452 * この機能はTableReader_Defaultのみ有効です。 1453 * 何も指定しない場合は、読取対象になります。 1454 * matchKeys と個数を合わせてください。 1455 * 1456 * @og.rev 6.4.6.0 (2016/05/27) 新規追加 1457 * 1458 * @param vals カラム列に対する正規表現(CSV形式文字) 1459 * @see #setMatchKeys( String ) 1460 */ 1461 public void setMatchVals( final String vals ) { 1462 clmAct.matchVals = getCSVParameter( vals ); 1463 } 1464 1465 /** 1466 * 【TAG】エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false)。 1467 * 1468 * @og.tag 1469 * 通常のエラーメッセージは、ラベル(長)が使われますが、これをラベル(短)を使いたい場合に、true にセットします。 1470 * ここでのラベル(短)は、タグ修飾なしの、ラベル(短)です。 1471 * 標準はfalse:利用しない=ラベル(長)です。 1472 * true/false以外を指定した場合はfalse扱いとします。 1473 * 1474 * ラベルリソースの概要説明があれば表示しますが、useSLabel="true" 時は、概要説明を表示しません。 1475 * 1476 * @og.rev 7.0.7.0 (2019/12/13) 新規追加 1477 * 1478 * @param prm SLABEL利用 [true:利用する/false:利用しない] 1479 */ 1480 public void setUseSLabel( final String prm ) { 1481 useSLabel = nval( getRequestParameter( prm ),useSLabel ); 1482 } 1483 1484 /** 1485 * 【TAG】システム定数でクラウド設定されていても、クラウド環境を使用しない場合、trueを指定します(初期値:false)。 1486 * 1487 * @og.tag 1488 * クラウド設定は、システム定数の『CLOUD_TARGET』と『CLOUD_BUCKET』の設定で自動的に使用しますが、 1489 * どうしてもローカルでのみ使いたい場合は、この属性を true に設定します。 1490 * 標準はfalse:設定どおりとなります。 1491 * true/false以外を指定した場合はfalse扱いとします。 1492 * 1493 * @og.rev 8.0.1.0 (2021/10/29) useLocal 属性を追加。 1494 * 1495 * @param flag ローカル環境のみ [true:ローカルのみ/false:設定どおり] 1496 */ 1497 public void setUseLocal( final String flag ) { 1498 useLocal = nval( getRequestParameter( flag ),useLocal ); 1499 } 1500 1501 /** 1502 * カラム処理を行う、内部クラス 1503 * 1504 * カラム個別に行う処理をまとめたクラスです。 1505 * omitNames : 読取対象外のカラム列を、外部(タグ)よりCSV形式で指定します 1506 * adjustColumns : 読取元ファイルのデータ変換を行うカラム列をカンマ指定します 1507 * checkColumns : 読取元ファイルの整合性チェックを行うカラム列をカンマ指定します 1508 * nullCheck : NULL チェックすべきカラム列をCSV形式(CSV形式)で指定します 1509 * 1510 * 名前配列設定で対象のカラムをピックアップし、値設定処理で、個々に処理します。 1511 * 1512 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction 新規作成 1513 */ 1514 protected static final class ColumnAction { 1515 private String omitNames ; // 読取対象外のカラム列を、外部(タグ)よりCSV形式で指定します 1516 private String adjustColumns ; // 読取元ファイルのデータ変換を行うカラム列をカンマ指定します 1517 private String checkColumns ; // 読取元ファイルの整合性チェックを行うカラム列をカンマ指定します 1518 private boolean isStrict ; // 7.3.2.0 (2021/03/19) 厳密にチェックするかどうか[true/false]を指定します(初期値:true) 1519 private String nullCheck ; // NULL チェックすべきカラム列をCSV形式(CSV形式)で指定します 1520 private int errRowCount = ERROR_ROW_COUNT; // NULL チェックすべきカラム列をCSV形式(CSV形式)で指定します 1521 private boolean useRenderer ; // 読取処理でKEY:VAL形式のコードリソースから、KEYを取り出す処理を行うかどうかを指定 1522 private boolean isDebug ; // debug フラグ 1523 private ErrorMessage errMsgObj ; // 6.2.5.0 (2015/06/05) 初期化します。 1524 1525 private int[] clmNos ; // 新名前配列に対応した、値配列のアドレス 1526 private int[] actFlg ; // カラム処理の実行有無のフラグ管理 1527 private String[] mtVals ; // 6.4.6.0 (2016/05/27) 新名前配列に対応した、判定処理用のデータ(正規表現) 1528 1529 private String[] matchKeys ; // 6.4.6.0 (2016/05/27) レコードの読取条件指定時のカラム列を配列で指定します 1530 private String[] matchVals ; // 6.4.6.0 (2016/05/27) レコードの読取条件指定時のカラム列に対応する正規表現データを配列で指定します 1531 1532 private boolean useRepeat ; // 7.3.0.0 (2021/01/06) 横持ちデータの繰り返し [true:使用する/false:使用しない] 1533 private RepeatDataChenge repDataCng ; // 7.3.0.0 (2021/01/06) 横持ちデータの繰り返し対応。 1534 1535 private static final int OMIT = -1; // OMIT だけ別。clmNosで、OMITフラグは除外する。 1536 private static final int ADJUST = 1; // adjustColumns 処理フラグ 1537 private static final int CHECK = 2; // checkColumns 処理フラグ 1538 private static final int NULL_CH = 4; // nullCheck 処理フラグ 1539 private static final int MAT_KYS = 8; // 6.4.6.0 (2016/05/27) matchKeys 処理フラグ 1540 1541 /** 1542 * 名前配列が設定された場合に、対象カラムのピックアップを行います。 1543 * このクラスでは、名前の再設定で、初期化されます。 1544 * 1545 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction 新規作成 1546 * @og.rev 6.2.5.0 (2015/06/05) ErrorMessage を、初期化します。 1547 * @og.rev 6.4.6.0 (2016/05/27) レコードの読取条件指定を追加 1548 * @og.rev 7.3.0.0 (2021/01/06) 横持ちデータの繰り返し対応。 1549 * 1550 * @param orgNms オリジナル名前配列 1551 * @return OMIT等考慮した、新名前配列 1552 */ 1553 public String[] makeNames( final String[] orgNms ) { 1554 if( useRepeat ) { repDataCng = new RepeatDataChenge(); } // 7.3.0.0 (2021/01/06) 初期化します。(Autoreaderチェックで、複数回呼ばれると重複するため) 1555 errMsgObj = new ErrorMessage( "Check Columns Error!" ); // 6.2.5.0 (2015/06/05) 初期化します。 1556 1557 // omit だけ、他のフラグセットと異なり、処理された数は、除外されるので逆になります。 1558 final int[] temp = new int[orgNms.length]; 1559 final int size = orgNms.length - actionFlagSet( omitNames, orgNms, OMIT, temp ); 1560 1561 if( size == 0 ) { // 有りえないが、omitNames="*" を誤って指定した場合にはありうる。 1562 final String errMsg = "カラムがありません。omitNames=[" + omitNames + "]"; 1563 throw new HybsSystemException( errMsg ); 1564 } 1565 1566 final String[] names = new String[size]; 1567 clmNos = new int[size]; 1568 int no = 0; 1569 for( int i=0; i<temp.length; i++ ) { 1570 if( temp[i] != OMIT ) { // 除外しない場合 1571 names[no] = orgNms[i]; // 名前配列に、オリジナルの名前をセット 1572 clmNos[no]= i; // カラムアドレスをセット(TableModelのカラム番号になる) 1573 no++ ; 1574 } 1575 } 1576 1577 actFlg = new int[size]; // 新名前配列に対応した、処理フラグを作成(フラグを加算) 1578 actionFlagSet( adjustColumns, names, ADJUST, actFlg ); // それぞれのフラグが加算される。 1579 actionFlagSet( checkColumns, names, CHECK, actFlg ); 1580 actionFlagSet( nullCheck, names, NULL_CH, actFlg ); 1581 1582 // 6.4.6.0 (2016/05/27) レコードの読取条件指定を追加。ほとんど使わない機能。 1583 if( matchKeys != null && matchKeys.length > 0 ) { 1584 final Map<String,String> keyMap = makeMatchMap( matchKeys , matchVals ); 1585 mtVals = new String[size]; 1586 for( int i=0; i<size; i++ ) { 1587 mtVals[i] = keyMap.get( names[i] ); 1588 if( mtVals[i] != null ) { actFlg[i] += MAT_KYS; } // 一致するカラムにフラグを加算する。 1589 } 1590 } 1591 1592 // 7.3.0.0 (2021/01/06) 横持ちデータの繰り返し対応 1593// return names; 1594 return useRepeat ? repDataCng.newNames( names ) : names ; 1595 } 1596 1597 /** 1598 * 値配列に対して、変換処理、チェック処理を行った結果を返します。 1599 * 1600 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction 新規作成 1601 * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 1602 * @og.rev 6.4.1.2 (2016/01/22) HybsOverflowException をthrow するとき、最大件数を引数に渡す。 1603 * @og.rev 6.4.6.0 (2016/05/27) レコードの読取条件指定を追加 1604 * @og.rev 7.2.9.4 (2020/11/20) spotbugs:null になっている可能性があるメソッドの戻り値を利用している 1605 * @og.rev 7.3.0.0 (2021/01/06) 横持ちデータの繰り返し対応。 1606 * @og.rev 7.3.2.0 (2021/03/19) isStrict:整合性チェック時に、厳密にチェックするかどうか[true/false]追加(初期値:true) 1607 * 1608 * @param vals 値配列 1609 * @param dbClms カラムオブジェクト配列 1610 * @param row 行番号(エラーメッセージの表示用) 1611 * @return 変換、チェック処理結果の値配列。このレコードを使用しない場合は、null を返します。 1612 */ 1613// public String[] clmAction( final String[] vals , final DBColumn[] dbClms , final int row ) { 1614 public List<String[]> clmAction( final String[] vals , final DBColumn[] dbClms , final int row ) { 1615 // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 1616 // 7.3.0.0 (2021/01/06) SpotBugs コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している 1617// if( clmNos == null || actFlg == null ) { 1618 if( clmNos == null || actFlg == null || errMsgObj == null ) { 1619 final String errMsg = "#makeNames(String[])を先に実行しておいてください。" ; 1620 throw new OgRuntimeException( errMsg ); 1621 } 1622 1623 final String[] rtnVals = new String[clmNos.length] ; 1624 boolean isError = false; 1625 1626 for( int no=0; no<clmNos.length; no++ ) { 1627 String val = vals[clmNos[no]]; 1628 if( useRenderer ) { // useRenderer(KEY:VAL) 処理 1629 val = dbClms[no].getReaderValue( val ); 1630 } 1631 if( (actFlg[no] & ADJUST) == ADJUST ) { // adjustColumns 処理 1632 val = dbClms[no].valueSet( val ); 1633 } 1634 if( (actFlg[no] & CHECK) == CHECK ) { // checkColumns 処理 1635// final ErrorMessage msg = dbClms[no].valueCheck( val ); 1636 final ErrorMessage msg = dbClms[no].valueCheck( val,isStrict ); // 7.3.2.0 (2021/03/19) 1637 if( msg.getKekka() > ErrorMessage.OK ) { 1638 isError = true; 1639 errMsgObj.append( row+1,msg ); 1640 } 1641 } 1642 if( (actFlg[no] & NULL_CH) == NULL_CH ) { // nullCheck 処理 1643 if( val == null || val.isEmpty() ) { 1644 isError = true; 1645 // ERR0012 : 指定のデータがセットされていません。(NULLエラー)。key={0} 1646 errMsgObj.addMessage( row+1,ErrorMessage.NG,"ERR0012",dbClms[no].getLabel() ); 1647 } 1648 } 1649 // 6.4.6.0 (2016/05/27) レコードの読取条件指定を追加 1650 // 6.9.8.0 (2018/05/28) FindBugs:コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している 1651 // このフラグが立っているということは、mtVals も、その値も、null ではない。 1652// if( (actFlg[no] & MAT_KYS) == MAT_KYS && !val.matches( mtVals[no] ) ) { return null; } // マッチしない場合は、null を返します。 1653 if( (actFlg[no] & MAT_KYS) == MAT_KYS && mtVals != null && !val.matches( mtVals[no] ) ) { return null; } // マッチしない場合は、null を返します。 1654 1655 rtnVals[no] = val; 1656 } 1657 1658 // 5.5.7.2 (2012/10/09) エラー時のデバッグ出力 1659 if( isDebug && isError ) { 1660 errMsgObj.addMessage( row+1,ErrorMessage.NG,"Debug",vals ); 1661 } 1662 1663 // isDebug == true 時には、件数は倍になるが、仕方がない。 1664 if( errMsgObj.size() > errRowCount ) { throw new HybsOverflowException( errRowCount ); } // 6.4.1.1 (2016/01/16) 1665 1666 // adjustColumns 処理結果を反映させます。 1667 // 7.3.0.0 (2021/01/06) 横持ちデータの繰り返し対応 1668// return rtnVals; 1669 if( useRepeat && repDataCng != null ) { 1670 return repDataCng.newValuesList( rtnVals ) ; 1671 } 1672 else { 1673 final List<String[]> rtnList = new ArrayList<>(); 1674 rtnList.add( rtnVals ); 1675 return rtnList; 1676 } 1677 } 1678 1679 /** 1680 * ErrorMessageオブジェクトを返します。 1681 * 1682 * @og.rev 6.2.5.0 (2015/06/05) 新規作成 1683 * 1684 * @return ErrorMessageオブジェクト 1685 */ 1686 public ErrorMessage getErrorMessage() { 1687 return errMsgObj ; 1688 } 1689 1690 /** 1691 * 読取処理で横持ちデータの繰り返しが存在する場合に、trueを指定します(初期値:false)。 1692 * 1693 * @og.rev 7.3.0.0 (2021/01/06) 横持ちデータの繰り返し対応。 1694 * 1695 * @param useRepeat 横持ちデータの繰り返し [true:使用する/false:使用しない] 1696 */ 1697 public void useRepeatClms( final boolean useRepeat ) { 1698 this.useRepeat = useRepeat ; 1699 } 1700 1701 /** 1702 * 処理実行可否を判断し、フラグをセットします。 1703 * 1704 * フラグのセットは、"|"(論理和)するのが良いのですが、OMITもここで判定している関係で、 1705 * 単なる加算にしています。 1706 * (マイナスをフラグにしているので、マイナスの論理和が良く判らないためです(^^)) 1707 * 1708 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction 新規作成 1709 * 1710 * @param clms 指定のカラム名 (CSV形式) 1711 * @param names 名前配列 1712 * @param flag 設定するフラグ(既存の配列に加算) 1713 * @param actFlg オリジナル名前配列 1714 * @return 処理を行った件数 1715 */ 1716 private int actionFlagSet( final String clms , final String[] names , final int flag , final int[] actFlg ) { 1717 int cnt = 0; 1718 if( clms != null ) { 1719 final String clmStr = ',' + clms.replaceAll( " ","" ) + ',' ; // 前後に カンマ(',') を追加、中間スペース削除 1720 for( int i=0; i<names.length; i++ ) { 1721 // "*" はループの外で判定して、2回それぞれでループを回す方が早い・・・かな? 1722 if( "*".equals( clms ) || clmStr.indexOf( ',' + names[i] + ',' ) >= 0 ) { 1723 cnt++ ; 1724 actFlg[i] += flag; // 一致するカラムにフラグを加算する。 1725 } 1726 } 1727 } 1728 return cnt ; 1729 } 1730 1731 /** 1732 * コードの読取条件指定のキーと値を関連付けるMapを作成します。 1733 * 1734 * ほとんど使用しない処理なので、できるだけ本体処理の影響が無いように、 1735 * メソッドを分けています。 1736 * このメソッドは、keys の、nullチェックを行ったうえで呼び出しています。 1737 * key,vals の個数が異なる場合は、エラーにしています。 1738 * 1739 * @og.rev 6.4.6.0 (2016/05/27) 新規作成 1740 * 1741 * @param keys 指定のカラム名配列(呼び出し前に、nullでないことを確認済み) 1742 * @param vals 指定の値配列 1743 * @return カラム名と値のMap 1744 * @og.rtnNotNull 1745 */ 1746 private Map<String,String> makeMatchMap( final String[] keys , final String[] vals ) { 1747 1748 // 6.4.6.0 (2016/05/27) レコードの読取条件指定を追加。個数判定 1749 if( vals != null && keys.length != vals.length ) { 1750 final String errMsg = "keys属性とvals属性の個数が合いません。" + CR 1751 + " keys=[" + keys.length + "]:KEYS=" + StringUtil.array2csv( keys ) + CR 1752 + " vals=[" + vals.length + "]:VLAS=" + StringUtil.array2csv( vals ) + CR ; 1753 throw new HybsSystemException( errMsg ); 1754 } 1755 1756 final Map<String,String> keyMap = new HashMap<>(); // 6.4.9.1 (2016/08/05) 1757 for( int i=0; i<keys.length; i++ ) { 1758 keyMap.put( keys[i] , vals[i] ); 1759 } 1760 1761 return keyMap; 1762 } 1763 } 1764 1765 /** 1766 * 繰り返しカラム処理を行う内部クラス 1767 * 1768 * 繰り返しカラムの廃位を [] で囲います。 1769 * 注文番号,品番,[納期1,数量1],[納期2,数量2]…[納期31,数量31],備考 と指定した場合、 1770 * 1771 * 注文番号,品番,備考,納期1,数量1 1772 * 注文番号,品番,備考,納期2,数量2 1773 * ・・・ 1774 * 注文番号,品番,備考,納期31,数量31 1775 * のように、縦型のデータに変更します。 1776 * 1777 * @og.rev 7.3.0.0 (2021/01/06) useRepeatClms 属性を追加。 1778 */ 1779 protected static final class RepeatDataChenge { 1780 private final List<Integer> ad1 = new ArrayList<>(); // 固定カラムのアドレス 1781 private final List<List<Integer>> ad2 = new ArrayList<>(); // 繰り返しカラムのアドレス 1782 // 8.0.0.0 (2021/07/31) Avoid using redundant field initializer for *** 1783// private int cnst = 0; // 固定カラムの個数 1784// private int rpet = 0; // 繰り返しカラムの個数([~]の間のカラムの数) 1785 private int cnst ; // 固定カラムの個数 1786 private int rpet ; // 繰り返しカラムの個数([~]の間のカラムの数) 1787 1788 /** 1789 * カラム名の配列を、繰り返しのアドレス設定と、繰り返し変換後のカラム配列を生成します。 1790 * 1791 * @param nms カラム名配列 1792 * @return 変換後のカラム名配列 1793 */ 1794 public String[] newNames( final String[] nms ) { 1795 final List<String> nms1 = new ArrayList<>(); // 固定カラムの名称 1796 final List<String> nms2 = new ArrayList<>(); // 繰り返しカラムの名称 1797 1798 List<Integer> lad = null ; // 繰り返しカラムの中間アドレスのリスト 1799 1800 boolean repCheck = true; // 繰り返しカラム名の取得は最初だけ 1801 boolean inFlag = false; // "[" でIN(true) "]" でOUT(false) の判定 1802 for( int i=0; i<nms.length; i++ ) { 1803 if( nms[i].startsWith( "[" ) ) { // 繰り返しカラム IN 1804 if( repCheck ) { nms2.add( nms[i].substring(1) ); } // 最初だけカラム名取得("["を削る) 1805 lad = new ArrayList<>(); 1806 lad.add(i); 1807 inFlag = true; 1808 } 1809 else if( nms[i].endsWith( "]" ) ) { // 繰り返しカラム OUT 1810 if( repCheck ) { nms2.add( nms[i].substring(0,nms[i].length()-1) ); repCheck = false; } // カラム名取得終了 1811 lad.add(i); 1812 ad2.add( lad ); // 繰り返しカラムの塊([~]の間)をまとめてセット 1813 inFlag = false; 1814 } 1815 else if( inFlag ) { // 繰り返しカラムの範囲内 1816 if( repCheck ) { nms2.add( nms[i] ); } // 最初だけカラム名取得 1817 lad.add(i); 1818 } 1819 else { // 固定カラム 1820 nms1.add( nms[i] ); 1821 ad1.add(i); 1822 } 1823 } 1824 1825 cnst = nms1.size(); // 固定カラムの個数 1826 rpet = nms2.size(); // 繰り返しカラムの個数([~]の間のカラムの数) 1827 1828 final List<String> names = new ArrayList<>( nms1 ); // 最終形のカラム一覧 1829 names.addAll( nms2 ); 1830 1831 return names.toArray( new String[names.size()] ) ; 1832 } 1833 1834 /** 1835 * 1行分のデータが設定された場合に、呼び出されます。 1836 * 1837 * 繰り返しデータに拡張したリストの中に、繰り返し変換後のデータ配列をセットして返します。 1838 * 1839 * @param vals 文字列値の1行分の配列 1840 * @return 変換後のデータ配列のリスト 1841 */ 1842 public List<String[]> newValuesList( final String[] vals ) { 1843 final List<String[]> valList = new ArrayList<>(); 1844 1845 // 6.4.6.0 (2016/05/27) レコードの読取条件指定を追加。条件に一致しなければ、null が返されます。 1846 if( vals != null ) { 1847 final String[] cnstVals = new String[cnst]; // 固定カラムの取得 1848 for( int i=0;i<cnst; i++ ) { 1849 cnstVals[i] = vals[ad1.get(i)]; // 固定カラムのアドレスから取得する。 1850 } 1851 1852 for( int j=0; j<ad2.size(); j++ ) { // 繰り返しカラム群の個数だけループする。 1853 final String[] allVals = new String[cnst + rpet]; // DBTableModelにセットするデータ(繰り返し毎に新規作成) 1854 System.arraycopy(cnstVals,0,allVals,0,cnst); // 固定カラムのデータをコピーする。 1855 1856 int k = cnst; 1857 final List<Integer> lad = ad2.get(j) ; // 繰り返しカラムのアドレス 1858 boolean isNN = false; // 繰り返しカラムのすべてのデータが null(空文字列)の場合は、登録しない。 1859 for( int i=0; i<rpet; i++ ) { 1860 final String val = vals[lad.get(i)]; 1861 if( !isNN && val != null && !val.trim().isEmpty() ) { isNN = true; } 1862 allVals[k++] = val; 1863 } 1864 if( isNN ) { 1865 valList.add( allVals ); // 値配列 1866 } 1867 } 1868 } 1869 return valList; 1870 } 1871 } 1872 1873 /** 1874 * AutoReader用の 簡易パラメータ管理用の内部クラスです。 1875 * 1876 * 3つのパラメータ(クラス、エンコード、サフィックス)を管理します。 1877 * 1878 * CLASS TableReader_**** クラス の ****部分を指定します。(Excel,Calc,Text,PIO など) 1879 * ENCODE クラスが、Text の場合のエンコード(UnicodeLittle,Windows-31J,UTF-8,EUC-JP など) 1880 * SUFIX 処理対象の拡張子(xls,xlsx,xlsm,ods など) 1881 * 1882 * @og.rev 6.2.5.0 (2015/06/05) 新規追加。AutoReader用の 簡易パラメータ管理用の内部クラス 1883 */ 1884 private static final class AutoReaderParam { 1885 public final String CLASS ; 1886 public final String ENCODE ; 1887 public final String SUFIX ; 1888 1889 /** 1890 * AutoReader用の 簡易パラメータ管理用の内部クラスのコンストラクターです。 1891 * 1892 * 3つのパラメータ(クラス、エンコード、サフィックス)を管理します。 1893 * 1894 * @og.rev 6.2.5.0 (2015/06/05) 新規追加。AutoReader用の 簡易パラメータ管理用の内部クラス 1895 * 1896 * @param cls TableReader_**** クラス の ****部分を指定します。(Excel,Calc,Text,PIO など) 1897 * @param enc クラスが、Text の場合のエンコード(UnicodeLittle,Windows-31J,UTF-8,EUC-JP など) 1898 * @param sfx 処理対象の拡張子(xls,xlsx,xlsm,ods など) nullの場合は、すべてを対象とする。 1899 */ 1900 public AutoReaderParam( final String cls , final String enc , final String sfx ) { 1901 CLASS = cls ; 1902 ENCODE = enc ; 1903 SUFIX = sfx == null ? null : ',' + sfx + ',' ; // 判定用なので、 1904 } 1905 1906 /** 1907 * 引数のサフィックスが、対象かどうか、判定します。 1908 * 対象の場合はtrue、対象でない場合はfalse を返します。 1909 * 1910 * @og.rev 6.2.5.0 (2015/06/05) 新規追加。AutoReader用の 簡易パラメータ管理用の内部クラス 1911 * 1912 * @param sufix 比較対象の拡張子(小文字のみ判定可能) 1913 * @return 対象かどうか[true:対象/false:対象外] 1914 */ 1915 public boolean useSufix( final String sufix ) { 1916 return SUFIX == null || SUFIX.contains( ',' + sufix + ',' ) ; 1917 } 1918 1919 /** 1920 * オブジェクトの文字列表現を返します。 1921 * 対象の場合はtrue、対象でない場合はfalse を返します。 1922 * 1923 * @og.rev 6.2.5.0 (2015/06/05) 新規追加。AutoReader用の 簡易パラメータ管理用の内部クラス 1924 * 1925 * @return このオブジェクトの文字列表現 1926 */ 1927 @Override 1928 public String toString() { 1929 return "class=[" + CLASS + "] , encode=[" + ENCODE + "] , sufix=[" + SUFIX + "]" ; 1930 } 1931 } 1932 1933 /** 1934 * このオブジェクトの文字列表現を返します。 1935 * 基本的にデバッグ目的に使用します。 1936 * 1937 * @return このクラスの文字列表現 1938 * @og.rtnNotNull 1939 */ 1940 @Override 1941 public String toString() { 1942 return ToString.title( this.getClass().getName() ) 1943 .println( "VERSION" ,VERSION ) 1944 .println( "separator" ,separator ) 1945 .println( "fileURL" ,fileURL ) 1946 .println( "filename" ,filename ) 1947 .println( "encode" ,encode ) 1948 .println( "readerClass" ,readerClass ) 1949 .println( "maxRowCount" ,maxRowCount ) 1950 .println( "displayMsg" ,displayMsg ) 1951 .println( "executeCount" ,executeCount ) 1952 .println( "modifyType" ,modifyType ) 1953 .println( "command" ,command ) 1954 .println( "tableId" ,tableId ) 1955 .println( "sheetName" ,sheetName ) 1956 .println( "sheetNos" ,sheetNos ) // 5.5.7.2 (2012/10/09) 1957 .println( "columns" ,columns ) 1958 .println( "useNumber" ,useNumber ) 1959 .println( "Other..." ,getAttributes().getAttribute() ) 1960 .fixForm().toString() ; 1961 } 1962}