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