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 static org.opengion.fukurou.util.StringUtil.*;
019
020import java.io.BufferedReader;
021import java.io.File;
022import java.io.FileNotFoundException;
023import java.io.IOException;
024import java.io.InputStreamReader;
025import java.io.ObjectInputStream;
026import java.io.ObjectOutputStream;
027import java.io.Reader;
028import java.io.UnsupportedEncodingException;
029import java.util.Locale ;
030
031import org.opengion.fukurou.model.FileOperation;
032import org.opengion.fukurou.util.Closer ;
033import org.opengion.fukurou.util.ErrorMessage;
034import org.opengion.fukurou.util.FileUtil;
035import org.opengion.fukurou.util.StringUtil ;
036import org.opengion.hayabusa.common.HybsSystem;
037import org.opengion.hayabusa.common.HybsSystemException;
038import org.opengion.hayabusa.db.DBColumn;
039import org.opengion.hayabusa.db.DBTableModel;
040import org.opengion.hayabusa.io.HybsFileOperationFactory;
041import org.opengion.hayabusa.io.TableReader;
042
043/**
044 * 指定のファイルを DBTableModelオブジェクトに読み取るファイル入力タグです。
045 *
046 * データ(DBTableModel)と、コントローラ(ReadTableタグ)を与えて、外部からコントロールすることで、
047 * 各種形式で データ(DBTableModel)を表示させることが できます。
048 * ReadTableタグ に対して、コマンドを与えることにより、内部のコントローラの実装に対応した
049 * 形式でデータを作成します。
050 * すべての読取の初期クラス名を リソースファイルの TABLE_READER_DEFAULT_CLASS で指定可能です。
051 * その場合、AutoReader を指定すると、Excel と Default(テキスト) を順番に試します。
052 *
053 * 入力件数を"DB.COUNT" キーでリクエストにセットしています。
054 *
055 * @og.formSample
056 * ●形式:
057 *     <og:readTable
058 *         command      = "NEW"
059 *         fileURL      = "{@USER.ID}"     読み取り元ディレクトリ名
060 *         filename     = "{@filename}"    読み取り元ファイル名
061 *         encode       = "UnicodeLittle"       読み取り元ファイルエンコード名
062 *         maxRowCount  = "10000"               読取最大件数(0:[無制限])
063 *     />
064 * ●body:なし
065 *
066 * ●Tag定義:
067 *   <og:readTable
068 *       readerClass        【TAG】実際に読み出すクラス名の略称(TableReader_**** の ****)をセットします({@og.doc03Link readerClass 初期値:Default})
069 *       fileURL            【TAG】読み取り元ディレクトリ名を指定します(初期値:FILE_URL)
070 *       filename           【TAG】ファイルを作成するときのファイル名をセットします (初期値:FILE_FILENAME[=file.xls])
071 *       encode             【TAG】ファイルを作成するときのファイルエンコーディング名をセットします(初期値:FILE_ENCODE)
072 *       maxRowCount        【TAG】読取時の最大取り込み件数をセットします (初期値:DB_MAX_ROW_COUNT[=1000])(0:[無制限])
073 *       separator          【TAG】可変長ファイルを作成するときの項目区切り文字をセットします
074 *       tableId            【TAG】(通常使いません)sessionから所得する DBTableModelオブジェクトの ID
075 *       command            【TAG】コマンド(NEW,RENEW)をセットします(初期値:NEW)
076 *       modifyType         【TAG】ファイル取り込み時の モディファイタイプ(A(追加),C(更新),D(削除))を指定します
077 *       displayMsg         【TAG】query の結果を画面上に表示するメッセージIDを指定します(初期値:MSG0033[ 件検索しました])
078 *       notfoundMsg        【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした])
079 *       sheetName          【TAG】EXCELファイルを読み込むときのシート名を設定します(初期値:指定なし)
080 *       sheetNos           【TAG】EXCELファイルを読み込むときのシート番号を複数設定できます(初期値:0)
081 *       sheetConstKeys     【TAG】EXCELファイルを読み込むときの固定値となるカラム名(CSV形式)
082 *       sheetConstAdrs     【TAG】EXCELファイルを読み込むときの固定値となるアドレス(行-列,行-列,・・・)
083 *       nullBreakClm       【TAG】カラム列に NULL が現れた時点で読み取りを中止します(複数Sheetの場合は、次のSheetを読みます)。
084 *       columns            【TAG】読み取り元ファイルのカラム列を、外部(タグ)より指定します
085 *       useNumber          【TAG】行番号情報を、使用している/していない[true/false]を指定します(初期値:true)
086 *       adjustColumns      【TAG】読み取り元ファイルのデータ変換を行うカラム列をカンマ指定します
087 *       checkColumns       【TAG】読み取り元ファイルの整合性チェックを行うカラム列をカンマ指定します
088 *       nullCheck          【TAG】NULL チェックすべきカラム列をカンマ区切り(CVS形式)で指定します
089 *       language           【TAG】タグ内部で使用する言語コード[ja/en/zh/…]を指定します
090 *       stopZero           【TAG】読込件数が0件のとき処理を続行するかどうか[true/false]を指定します(初期値:false[続行する])
091 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session)
092 *       mainTrans          【TAG】(通常使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:false)
093 *       skipRowCount       【TAG】(通常は使いません)データの読み飛ばし件数を設定します
094 *       useRenderer        【TAG】読取処理でラベルをコードリソースに逆変換を行うかどうかを指定します (初期値:USE_TABLE_READER_RENDERER[=false])
095 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 5.7.7.2 (2014/06/20)
096 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 5.7.7.2 (2014/06/20)
097 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:true) 5.7.7.2 (2014/06/20)
098 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:true) 5.7.7.2 (2014/06/20)
099 *       storageType            【TAG】読み取り元ストレージタイプを指定します
100 *       bucketName                     【TAG】読み取り元バケット名を指定します
101 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
102 *   />
103 *
104 * ●使用例
105 *
106 *     <og:readTable
107 *         command        = "NEW"
108 *         readerClass    = "Fixed"               固定長データの読み取り
109 *         modifyType     = "{@modifyType}"  読取時のモディファイタイプ(A,C等)
110 *         fileURL        = "{@USER.ID}"     読み取り元ディレクトリ名
111 *         filename       = "{@filename}"    読み取り元ファイル名
112 *         encode         = "Shift_JIS"           読み取り元ファイルエンコード名
113 *         maxRowCount    = "10000"               読取最大件数(0:[無制限])
114 *         columns        = "OYA,KO,HJO,SU,DYSTR,DYEND"   #NAME に対応するカラム列
115 *         useNumber      = "false"               行番号の存在しないデータを読み取ります。
116 *         adjustColumns  = "OYA,KO,HJO,SU"       データ変換するカラム列("*" で全カラム)
117 *         checkColumns   = "OYA,KO,HJO,SU"       整合性チェックするカラム列("*" で全カラム)
118 *         nullCheck      = "OYA,KO,SU"           NULLチェックを実行します("*" で全カラム)
119 *         stopZero       = "true"                取得0件の場合に以降の処理を停止します
120 *         skipRowCount   = "4"                   データの読み飛ばし件数(読み込み開始は、この数字+1行目から)
121 *     />
122 *
123 * @og.rev 5.10.9.0 (2019/03/01) oota クラウドストレージ対応を追加。(Fileクラスを拡張)
124 *
125 * @og.group ファイル入力
126 *
127 * @version  4.0
128 * @author   Kazuhiko Hasegawa
129 * @since    JDK5.0,
130 */
131public class ReadTableTag extends CommonTagSupport {
132        //* このプログラムのVERSION文字列を設定します。   {@value} */
133        private static final String VERSION = "5.7.7.2 (2014/06/20)" ;
134
135        private static final long serialVersionUID = 577220140620L ;
136
137        private static final int ERROR_ROW_COUNT = 200 ;        // 4.0.0 (2007/05/25)
138
139        /** command 引数に渡す事の出来る コマンド  新規作成 {@value} */
140        public static final String CMD_NEW   = "NEW" ;
141        /** command 引数に渡す事の出来る コマンド  再検索 {@value} */
142        public static final String CMD_RENEW = "RENEW" ;
143
144        private static final String[] COMMAND_LIST = new String[] { CMD_NEW , CMD_RENEW };
145
146        // 5.9.25.2 (2017/10/27)
147        // 5.10.9.0 (2019/03/01) DELETE FileOperationInterface対応
148//      private final String CLOUD_TARGET = HybsSystem.sys( "CLOUD_TARGET" );
149
150        private String  separator               = TableReader.TAB_SEPARATOR;     // 項目区切り文字
151        private String  fileURL                 = HybsSystem.sys( "FILE_URL" );
152        private String  filename                = HybsSystem.sys( "FILE_FILENAME"               );       // ファイル名
153        private String  encode                  = HybsSystem.sys( "FILE_ENCODE"                 );       // ファイルエンコーディング  "JISAutoDetect" ,"JIS", "EUC_JP", "MS932", "SJIS" , "Windows-31J" , "Shift_JIS"
154        private String  readerClass     = HybsSystem.sys( "TABLE_READER_DEFAULT_CLASS" );               // 3.8.5.3 (2006/08/07)
155        private int             maxRowCount             = -1;
156        private String  displayMsg              = HybsSystem.sys( "VIEW_DISPLAY_MSG" );
157        private String  notfoundMsg             = "MSG0077";    // 対象データはありませんでした。
158        private int     executeCount    = -1;                   // 検索/実行件数
159        private String  modifyType              = null;
160        private String adjustColumns    = null;         // 3.6.0.2 (2004/10/04) 取り込み時チェック
161        private String checkColumns             = null;         // 3.6.0.2 (2004/10/04) 取り込み時チェック
162        private String nullCheck                = null;         // 3.8.0.2 (2005/06/30) nullチェック確認
163
164        private transient DBTableModel table      = null;
165        private String          command         = CMD_NEW;
166        private String          tableId         = HybsSystem.TBL_MDL_KEY ;
167        private String          sheetName       = null ;                // 3.5.4.2 (2003/12/15)
168        private String          sheetNos        = null ;                // 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるようにする。
169        private String          sheetConstKeys  = null ;        // 5.5.8.2 (2012/11/09) 固定値となるカラム名(CSV形式)
170        private String          sheetConstAdrs  = null ;        // 5.5.8.2 (2012/11/09) 固定値となるアドレス(行-列,行-列,・・・)
171        private String          nullBreakClm    = null;         // 5.5.8.2 (2012/11/09) 取込み条件/Sheet BREAK条件
172
173        // 3.5.4.5 (2004/01/23) 外部よりカラム列(カンマ区切り)を指定できるようにする。
174        private String          columns         = null;
175        private boolean         useNumber       = true;                 // 3.7.0.5 (2005/04/11)
176
177        private boolean         stopZero        = false;                // 4.3.7.0 (2009/06/01) stopZero属性追加
178
179        // 5.1.8.0 (2010/07/01) AutoReaderのCalc対応
180        private static final String[] AUTO_READER_CLASS  = new String[] { "Excel","Calc","Default"      ,"Default"     };
181        private static final String[] AUTO_READER_ENCODE = new String[] { null   ,null  ,"UnicodeLittle","Windows-31J" };
182
183        private boolean isMainTrans             = true;                 // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し
184        private int             skipRowCount    = 0;                    // 5.1.6.0 (2010/05/01) データの読み飛ばし設定
185
186        // 5.9.8.1 (2016/05/13) 追加
187        private String[]        matchKeys       = null;
188        private String[]        matchVals       = null;
189
190        // 5.2.1.0 (2010/10/01) 読取処理でコードリソースのラベル変換を行うかどうか
191        private boolean useRenderer             = HybsSystem.sysBool( "USE_TABLE_READER_RENDERER" );    // 5.2.1.0 (2010/10/01)
192
193        private String storageType              = null;                 // 5.10.9.0 (2019/03/01) ADD
194        private String bucketName               = null;                 // 5.10.9.0 (2019/03/01) ADD
195        
196        /**
197         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
198         *
199         * @og.rev 3.0.1.4 (2003/03/17) displayMsg が 0Byteの場合は、件数も表示しないように変更。
200         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
201         * @og.rev 3.5.4.1 (2003/12/01) 引数の BufferedReader を、InputStream に変更。
202         * @og.rev 3.5.4.3 (2004/01/05) 引数の InputStream を、 BufferedReader に戻す。
203         * @og.rev 3.5.6.5 (2004/08/09) 暫定的に、DBTableModelを先行削除します。
204         * @og.rev 3.6.0.0 (2004/09/24) DBTableModel の先行削除は、scope="session" の場合のみ。
205         * @og.rev 3.6.0.2 (2004/10/04) 取り込み時チェック用に、checkColumns,adjustColumns 属性追加
206         * @og.rev 3.6.0.8 (2004/11/19) DBTableModel をセーブする時に、トランザクションチェックを行います。
207         * @og.rev 3.8.5.3 (2006/08/07) readerClassが "Excel"でエラーが発生したとき、もう一度Defaultで再読取を行います。
208         * @og.rev 4.0.0.0 (2007/10/12) checkTableColumn 前に、modifyType 設定を行います。
209         * @og.rev 4.0.0.0 (2007/10/18) メッセージリソース統合( getResource().getMessage ⇒ getResource().getLabel )
210         * @og.rev 4.3.1.1 (2008/10/08) columnsが指定されている場合は、AutoReader禁止
211         * @og.rev 4.3.7.0 (2009/06/01) stopZero機能,DB.COUNTリクエストキーへ読込件数セットを追加
212         * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。
213         * @og.rev 5.1.8.0 (2010/07/01) AutoReaderのCalc対応
214         * @og.rev 5.1.9.0 (2010/08/01) AutoReaderでのExceptionの判定をThrowableに変更
215         * @og.rev 5.7.1.2 (2013/12/20) tempMsg.toString() ⇒ errMsg 変更
216         * @og.rev 5.7.7.2 (2014/06/20) caseKey,caseVal,caseNN,caseNull 属性を追加
217         *
218         * @return      後続処理の指示
219         */
220        @Override
221        public int doEndTag() {
222                debugPrint();           // 4.0.0 (2005/02/28)
223                // 5.7.7.2 (2014/06/20) caseKey,caseVal,caseNN,caseNull 属性を追加
224                if( !useTag() ) { return EVAL_PAGE ; }
225
226                if( check( command, COMMAND_LIST ) ) {
227                        useMainTrans( isMainTrans );                    // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し
228                        startQueryTransaction( tableId );               // 3.6.0.8 (2004/11/19)
229
230                        // 3.5.6.5 (2004/08/09) 削除するのは、セッションのオブジェクトでよい。
231                        // 3.6.0.0 (2004/09/24) 削除するのは、scope="session" の場合のみ。
232                        if( "session".equals( getScope() ) ) {
233                                removeSessionAttribute( tableId );
234                                removeSessionAttribute( HybsSystem.VIEWFORM_KEY );
235                        }
236
237                        if( maxRowCount < 0 ) {
238                                maxRowCount     = sysInt( "DB_MAX_ROW_COUNT" );
239                        }
240
241                        // ファイル の読み込み:AutoReader 処理
242                        BufferedReader pw = null;
243                        final String[] READER_CLASS  ;
244                        final String[] READER_ENCODE ;
245                        if( "AutoReader".equalsIgnoreCase( readerClass ) ) {
246                                // 4.3.1.1 (2008/10/08)
247                                if( columns != null && columns.length() > 0 ) {
248                                        String errMsg = "columnsが指定されている場合は、readerClass=\"AutoReader\"は使えません";
249                                        throw new HybsSystemException( errMsg ); // 4.3.4.4 (2009/01/01)
250                                }
251                                READER_CLASS  = AUTO_READER_CLASS ;
252                                READER_ENCODE = AUTO_READER_ENCODE;
253                        }
254                        else {
255                                READER_CLASS  = new String[] { readerClass };
256                                READER_ENCODE = new String[] { encode };
257                        }
258
259                        StringBuilder tempMsg = new StringBuilder();
260                        for( int i=0; i<READER_CLASS.length; i++ ) {
261                                readerClass = READER_CLASS[i];
262                                encode      = READER_ENCODE[i];
263
264                                try {
265                                        // 5.1.8.0 (2010/07/01) AutoReaderのCalc対応
266                                        if( "Excel".equalsIgnoreCase( readerClass ) || "Calc".equalsIgnoreCase( readerClass ) ) {
267                                                create( null );
268                                        }
269                                        else {
270                                                pw = getBufferedReader();
271                                                create( pw );
272                                        }
273                                        // 成功すれば、エラーメッセージをクリアして、その場で抜ける。
274                                        tempMsg = null;
275                                        break;
276                                }
277                                // 3.8.5.3 (2006/08/07) readerClassが "Excel"でエラーが発生したとき、もう一度Defaultで再読取を行います。
278                                // 5.1.9.0 (2010/08/01) RuntimeException系のExceptionがキャッチできないため、Throwableで受ける
279                                catch( Throwable th ) {
280                                        tempMsg.append( "readerClass=["  ).append( readerClass )
281                                                        .append( "],encode=["    ).append( encode )
282                                                        .append( "] Error!"      ).append( HybsSystem.CR )
283                                                        .append( th.getMessage() ).append( HybsSystem.CR ) ;
284                                }
285                                finally {
286                                        Closer.ioClose( pw );           // 4.0.0 (2006/01/31) close 処理時の IOException を無視
287                                }
288                        }
289
290                        if( tempMsg != null ) { // 最後までエラーがあれば、例外処理を発行します。
291                                String errMsg = tempMsg.toString();
292                                System.err.print( errMsg );
293                                throw new HybsSystemException( errMsg );                // 5.7.1.2 (2013/12/20) msg ⇒ errMsg 変更
294                        }
295
296                        if( table != null ) {
297                                // 3.6.0.2 (2004/10/04)
298                                // 4.0.0.0 (2007/10/12) checkTableColumn 前に、modifyType 設定を行います。
299                                executeCount = table.getRowCount();
300                                if( modifyType != null ) {
301                                        for( int row=0; row<executeCount; row++ ) {
302                                                table.setModifyType( row,modifyType );
303                                        }
304                                }
305
306                                ErrorMessage errMsg = checkTableColumn( table );
307                                if( errMsg != null && ! errMsg.isOK()) {
308                                        jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg,getResource() ) );
309                                        return SKIP_PAGE ;
310                                }
311
312                        }
313                        // 3.6.0.8 (2004/11/19) トランザクションチェックを行います。
314                        if( ! commitTableObject( tableId, table ) ) {
315                                jspPrint( "ReadTableTag Query処理が割り込まれました。DBTableModel は登録しません。" );
316                                return SKIP_PAGE ;
317                        }
318
319                        StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_SMALL );
320
321                        // 実行件数の表示 command="NEW" のときのみ、displayMsg を表示させます。
322                        // 4.0.0 (2005/11/30) 出力順の変更。一番最初に出力します。
323                        if( CMD_NEW.equals( command ) ) {
324                                if( executeCount > 0 && displayMsg != null && displayMsg.length() > 0 ) {
325                                        buf.append( executeCount );
326                                        buf.append( getResource().getLabel( displayMsg ) );
327                                        buf.append( HybsSystem.BR );
328                                }
329                                else if( executeCount == 0 && notfoundMsg != null && notfoundMsg.length() > 0 ) {
330                                        buf.append( getResource().getLabel( notfoundMsg ) );
331                                        buf.append( HybsSystem.BR );
332                                }
333                        }
334
335                        // 4.3.7.0 (2009/06/01) 読込件数を、"DB.COUNT" キーでリクエストにセットする。
336                        setRequestAttribute( "DB.COUNT"   , String.valueOf( executeCount ) );
337
338                        jspPrint( buf.toString() );
339                }
340
341                // 4.3.7.0 (2009/06/01) stopZero機能を追加
342                final int rtnCode ;
343                if( executeCount == 0 && stopZero )     {
344                        rtnCode = SKIP_PAGE;
345                }
346                else {
347                        rtnCode = EVAL_PAGE;
348                }
349
350                return rtnCode ;
351        }
352
353        /**
354         * タグリブオブジェクトをリリースします。
355         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
356         *
357         * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
358         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
359         * @og.rev 3.1.3.0 (2003/04/10) FILE_ENCODE から、エンコード情報を取得する。
360         * @og.rev 3.1.4.0 (2003/04/18) command 属性に、初期値(NEW)を設定する。
361         * @og.rev 3.5.4.2 (2003/12/15) EXCELのシート名を指定できるように変更。
362         * @og.rev 3.5.4.5 (2004/01/23) 外部よりカラム列(カンマ区切り)を指定できるようにする。
363         * @og.rev 3.6.0.2 (2004/10/04) checkColumns,adjustColumns,allColumnCheck 属性追加
364         * @og.rev 3.7.0.5 (2005/04/11) useNumber 属性を追加します。
365         * @og.rev 3.8.0.2 (2005/06/30) nullCheck 属性追加
366         * @og.rev 3.8.5.3 (2006/08/07) readerClass 属性の初期値をシステムリソースより取得します。
367         * @og.rev 4.3.7.0 (2009/06/01) stopZero属性追加
368         * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。
369         * @og.rev 5.1.6.0 (2010/05/01) データの読み飛ばし設定 skipRowCount 属性追加
370         * @og.rev 5.2.1.0 (2010/10/01) 読取処理でコードリソースのラベル変換を行うかどうか useRenderer 属性追加
371         * @og.rev 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるように、sheetNos属性追加
372         * @og.rev 5.5.8.2 (2012/11/09) 固定値となるカラム名、アドレスの指定のための、sheetConstKeys、sheetConstAdrs属性追加
373         * @og.rev 5.5.8.2 (2012/11/09) カラム列に NULL が現れた時点で読み取りを中止する、nullBreakClm属性追加
374         * @og.rev 5.9.8.1 (2016/05/13) 読込条件の追加
375         */
376        @Override
377        protected void release2() {
378                super.release2();
379                separator               = TableReader.TAB_SEPARATOR;   // 項目区切り文字
380                fileURL                 = HybsSystem.sys( "FILE_URL" );
381                filename                = HybsSystem.sys( "FILE_FILENAME" );   // ファイル名
382                encode                  = HybsSystem.sys( "FILE_ENCODE"   );   // ファイルエンコーディング  "JISAutoDetect" ,"JIS", "EUC_JP", "MS932", "SJIS" , "Windows-31J" , "Shift_JIS"
383                readerClass             = HybsSystem.sys( "TABLE_READER_DEFAULT_CLASS" );               // 3.8.5.3 (2006/08/07)
384                maxRowCount             = -1;
385                displayMsg              = HybsSystem.sys( "VIEW_DISPLAY_MSG" );
386                notfoundMsg             = "MSG0077";    // 対象データはありませんでした。
387                executeCount    = -1;                   // 検索/実行件数
388                modifyType              = null;
389                command                 = CMD_NEW;
390                table                   = null;
391                tableId                 = HybsSystem.TBL_MDL_KEY ;
392                sheetName               = null;         // 3.5.4.2 (2003/12/15)
393                sheetNos                = null ;        // 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるようにする。
394                sheetConstKeys  = null ;        // 5.5.8.2 (2012/11/09) 固定値となるカラム名(CSV形式)
395                sheetConstAdrs  = null ;        // 5.5.8.2 (2012/11/09) 固定値となるアドレス(行-列,行-列,・・・)
396                nullBreakClm    = null;         // 5.5.8.2 (2012/11/09) 取込み条件/Sheet BREAK条件
397                columns                 = null;         // 3.5.4.5 (2004/01/23)
398                useNumber               = true;         // 3.7.0.5 (2005/04/11)
399                adjustColumns   = null;         // 3.6.0.2 (2004/10/04) 取り込み時チェック
400                checkColumns    = null;         // 3.6.0.2 (2004/10/04) 取り込み時チェック
401                nullCheck               = null;         // 3.8.0.2 (2005/06/30)
402                stopZero                = false;        // 4.3.7.0 (2009/06/01) soptZero追加
403                isMainTrans             = true;         // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し
404                skipRowCount    = 0;            // 5.1.6.0 (2010/05/01) データの読み飛ばし設定
405                matchKeys               = null;         // 5.9.8.1 (2016/05/13) 読込条件設定
406                matchVals               = null;         // 5.9.8.1 (2016/05/13) 読込条件設定
407                useRenderer             = HybsSystem.sysBool( "USE_TABLE_READER_RENDERER" );    // 5.2.1.0 (2010/10/01)
408                storageType             = null;         // 5.10.9.0 (2019/03/01) ADD
409                bucketName              = null;         // 5.10.9.0 (2019/03/01) ADD
410        }
411
412        /**
413         * TableReader の実オブジェクトを生成して,BufferedReader に書き込みます。
414         *
415         * @og.rev 3.5.4.1 (2003/12/01) 引数の BufferedReader を、InputStream に変更。
416         * @og.rev 3.5.4.2 (2003/12/15) TableReader のサブクラス名変更。
417         * @og.rev 3.5.4.2 (2003/12/15) EXCELのシート名を指定できるように変更。
418         * @og.rev 3.5.4.3 (2004/01/05) 引数の InputStream を、 BufferedReader に戻す。
419         * @og.rev 3.5.4.5 (2004/01/23) TableReader に、encode を渡すように変更。
420         * @og.rev 3.5.6.0 (2004/06/18) 各種プラグイン関連付け設定を、システムパラメータ に記述します。
421         * @og.rev 3.7.0.5 (2005/04/11) useNumber 属性を追加します。
422         * @og.rev 4.0.0.0 (2005/01/31) キーの指定を、TableReader. から、TableReader_ に変更します。
423         * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更
424         * @og.rev 5.1.6.0 (2010/05/01) データの読み飛ばし設定 skipRowCount 属性追加
425         * @og.rev 5.2.1.0 (2010/10/01) 読取処理でコードリソースのラベル変換を行うかどうか設定 useRenderer 属性追加
426         * @og.rev 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるように、sheetNos属性追加
427         * @og.rev 5.5.8.2 (2012/11/09) 固定値となるカラム名、アドレスの指定のための、sheetConstKeys、sheetConstAdrs属性追加
428         * @og.rev 5.5.8.2 (2012/11/09) カラム列に NULL が現れた時点で読み取りを中止する、nullBreakClm属性追加
429         * @og.rev 5.9.8.1 (2016/05/13) match対応
430         * @og.rev 5.9.25.2 (2017/10/27) クラウドストレージ対応
431         * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応を追加。
432         *
433         * @param       out     出力するBufferedReaderオブジェクト
434         */
435        protected void create( final BufferedReader out )  {
436                String className = HybsSystem.sys( "TableReader_" + readerClass ) ;             // 4.0.0 (2005/01/31)
437                TableReader reader = (TableReader)HybsSystem.newInstance( className );  // 3.5.5.3 (2004/04/09)
438                reader.setResourceManager( getResource() );     // 4.0.0 (2005/01/31)
439                reader.setSeparator( separator );
440                reader.setEncode( encode );                                             // 3.5.4.5 (2004/01/23)
441                reader.setColumns( columns );                                   // 3.5.4.5 (2004/01/23)
442                reader.setUseNumber( useNumber );                               // 3.7.0.5 (2005/04/11)
443                reader.setMaxRowCount( maxRowCount );
444                reader.setSkipRowCount( skipRowCount );                 // 5.1.6.0 (2010/05/01)
445                reader.setUseRenderer( useRenderer );                   // 5.2.1.0 (2010/10/01)
446                reader.setMatchKeys( matchKeys );                               // 5.9.8.1 (2016/05/13)
447                reader.setMatchVals( matchVals );                               // 5.9.8.1 (2016/05/13)
448                reader.setDebug( isDebug() );                                   // 5.5.7.2 (2012/10/09) デバッグ情報を出力するかどうかを指定
449                if( reader.isExcel() ) {                                                // 3.5.4.3 (2004/01/05)
450                        // 5.9.25.2 (2017/10/27)
451                        String filePath = "";
452                        try{
453                                // 5.10.9.0 (2019/03/01) ADD
454                                FileOperation fileOperation = HybsFileOperationFactory.create(storageType, bucketName, fileURL, filename);
455                                if(!fileOperation.isLocal()) {
456                                        // クラウド上のファイルをサーバにダウンロードする。
457                                        filePath = downloadStorageFile();
458                                }
459
460                                reader.setFilename( HybsSystem.url2dir( StringUtil.urlAppend( fileURL,filename )));
461                                reader.setSheetName( sheetName );                       // 3.5.4.2 (2003/12/15)
462                                reader.setSheetNos( sheetNos );                         // 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるようにする。
463                                reader.setSheetConstData( sheetConstKeys,sheetConstAdrs ) ;             // 5.5.8.2 (2012/11/09) 固定値となるカラム名、アドレスの指定
464                                reader.setNullBreakClm( nullBreakClm ) ;        // 5.5.8.2 (2012/11/09) 取込み条件/Sheet BREAK条件
465                                reader.readDBTable();
466
467                        // 5.10.9.0 (2019/03/01) ADD
468                        }finally{
469                                FileOperation fileOperation = HybsFileOperationFactory.create(storageType, bucketName, filePath);
470                                if(!fileOperation.isLocal()) {
471                                        // サーバにダウンロードしたファイルを削除
472                                        File file = new File(filePath);
473                                        if(file.exists()){
474                                                file.delete();
475                                        }
476                                }
477                        }
478                }
479                else {
480                        reader.readDBTable( out );
481                }
482                table = reader.getDBTableModel();
483        }
484
485        /**
486         * クラウドストレージのExcelファイルをサーバにダウンロード。
487         * (POIで処理する必要があるため)
488         *
489         * @og.rev 5.9.25.2 (2017/10/27) 新規作成
490         * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応の追加。
491         *
492         * @return filePath サーバのファイルパス
493         */
494        private String downloadStorageFile() {
495                String filePath = HybsSystem.url2dir( StringUtil.urlAppend( fileURL,filename ));
496                String directory = HybsSystem.url2dir( fileURL );
497                // 5.10.9.0 (2019/03/01) MODIFY
498                FileOperation targetFile = HybsFileOperationFactory.create(storageType, bucketName, directory, filename);
499                
500                // 指定のファイルがクラウドストレージに存在しない場合は、エラー
501                if(!targetFile.isFile()) {
502                        StringBuilder errMsg = new StringBuilder(HybsSystem.BUFFER_MIDDLE);
503                        errMsg.append("指定のファイルが見つかりません。path : ").append(targetFile.getAbsolutePath());
504                        throw new HybsSystemException(errMsg.toString());
505                }
506                
507                // コピー先ファイルパス
508                File file = new File(filePath);
509                FileUtil.copy(targetFile, file);
510
511                return filePath;
512        }
513
514        /**
515         * BufferedReader を取得します。
516         *
517         * ここでは、一般的なファイル出力を考慮した BufferedReader を作成します。
518         *
519         * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更
520         * @og.rev 3.1.3.0 (2003/04/10) FILE_ENCODE から、エンコード情報を取得する。
521         * @og.rev 3.5.4.1 (2003/12/01) 引数の BufferedReader を、InputStream に変更。
522         * @og.rev 3.5.4.3 (2004/01/05) 引数の InputStream を、 BufferedReader に戻す。
523         * @og.rev 3.5.5.9 (2004/06/07) FileUtil.getBufferedReader を使用
524         * @og.rev 5.9.25.2 (2017/10/27) クラウドストレージ対応
525         * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応を追加。
526         *
527         * @return      ファイル読取BufferedReaderオブジェクト
528         */
529        private BufferedReader getBufferedReader() {
530                if( filename == null ) {
531                        String errMsg = "ファイル名がセットされていません。";
532                        throw new HybsSystemException( errMsg );
533                }
534
535                // 2017/10/20 DELETE 後の判定処理内に移動
536                // 通常の処理
537//              String directory = HybsSystem.url2dir( fileURL );
538//              File file = new File( StringUtil.urlAppend( directory,filename ) );
539//
540//              BufferedReader out = FileUtil.getBufferedReader( file,encode );
541
542                BufferedReader out = null;
543                
544                // 5.10.9.0 (2019/03/01) MODIFY FileOperationクラスを利用したBufferdReaderの生成に
545//              // 通常の処理
546//              String directory = HybsSystem.url2dir( fileURL );
547//              File file = new File( StringUtil.urlAppend( directory,filename ) );
548//
549//              out = FileUtil.getBufferedReader( file,encode );
550                
551                String directory = HybsSystem.url2dir( fileURL );
552                FileOperation file = HybsFileOperationFactory.create(storageType, bucketName, directory, filename);
553
554                Reader reader = null;
555                try {
556                        reader = new InputStreamReader( file.read(), encode );
557                        out = new BufferedReader( reader );
558                        
559                }catch(UnsupportedEncodingException ue) {
560                        String errMsg = "サポートされていない文字コードです。encode:" + encode;
561                        throw new HybsSystemException(errMsg);
562                }catch(FileNotFoundException fe) {
563                        String errMsg = "ファイルが存在しません。path:" + file.getPath();
564                        throw new HybsSystemException(errMsg);
565                }
566                
567                return out ;
568        }
569
570        /**
571         * カラム文字列(CSV形式)から、カラム番号配列を作成します。
572         * 簡易メソッドです。
573         * 引数が、"*" の場合は、全カラムを指定したことになります。
574         * null の場合は、サイズが 0 の配列を返します。
575         *
576         * @og.rev 4.0.0.0 (2007/05/25) 新規作成
577         *
578         * @param       clms    カラム文字列(CSV形式)
579         * @param       table   DBTableModelオブジェクト
580         *
581         * @return      カラム番号配列(無い場合は、長さ0の配列)
582         */
583        private int[] makeClmNos( final String clms,final DBTableModel table ) {
584                final int[] clmNo;
585
586                if( clms == null ) {
587                        clmNo = new int[0];
588                }
589                else if( "*".equals( clms ) ) {
590                        int size = table.getColumnCount();
591                        clmNo = new int[size];
592                        for( int i=0; i<size; i++ ) {
593                                clmNo[i] = i;
594                        }
595                }
596                else {
597                        String[] clmStr = StringUtil.csv2Array( clms );
598                        int size = clmStr.length;
599                        clmNo = new int[size];
600                        for( int i=0; i<size; i++ ) {
601                                clmNo[i] = table.getColumnNo( clmStr[i] );
602                        }
603                }
604
605                return clmNo;
606        }
607
608        /**
609         * checkColumns に指定されたカラムをチェックします。
610         * カラムオブジェクトのDBType属性に対応したチェックを行います。
611         * チェック結果で、エラーが発生した場合は、ErrorMessage オブジェクトを
612         * 返します。
613         * DBColumn#valueCheck( String ) の結果のErrorMessageをすべて append
614         * していきます。
615         * useAdjust==true で、かつ、エラーがない場合は、adjustColumns 処理結果を
616         * DBTableModel に反映させます。
617         * debug=true で、エラー時の詳細なデータを出力します。
618         *
619         * @og.rev 3.6.0.2 (2004/10/04) 新規作成
620         * @og.rev 3.8.0.2 (2005/06/30) nullチェック確認
621         * @og.rev 4.0.0.0 (2007/05/25) 処理順序書き換え
622         *
623         * @param       table   DBTableModelオブジェクト
624         *
625         * @return      カラムキー + 値 のエラーメッセージオブジェクト
626         */
627        private ErrorMessage checkTableColumn( final DBTableModel table ) {
628                ErrorMessage errMsg = new ErrorMessage( "Check Columns Error!" );
629
630                int rowCnt = table.getRowCount();
631                int[] adjClmNo = makeClmNos( adjustColumns,table );
632                int[] chkClmNo = makeClmNos( checkColumns,table );
633                int[] nllclmNo = makeClmNos( nullCheck,table );
634
635                boolean useAdjust = adjClmNo.length > 0 ;
636
637                for( int row=0; row<rowCnt; row++ ) {
638                        String[]   vals   = table.getValues( row );
639                        DBColumn[] dbClms = table.getDBColumns();
640                        boolean isError = false;                                                // 5.5.7.2 (2012/10/09) エラー時のフラグ。ループでクリアする。
641
642                        // adjustColumns 処理
643                        for( int i=0; i<adjClmNo.length; i++ ) {
644                                int no = adjClmNo[i];
645                                vals[no] = dbClms[no].valueSet( vals[no] );
646                        }
647
648                        // checkColumns 処理
649                        for( int i=0; i<chkClmNo.length; i++ ) {
650                                int no = chkClmNo[i];
651                                ErrorMessage msg = dbClms[no].valueCheck( vals[no] );
652                                if( msg.getKekka() > ErrorMessage.OK ) {
653                                        isError = true;
654                                        errMsg.append( row+1,dbClms[no].valueCheck( vals[no] ) );
655                                }
656                        }
657
658                        // nullCheck 処理
659                        for( int i=0; i<nllclmNo.length; i++ ) {
660                                int no = nllclmNo[i];
661                                if( vals[no] == null || vals[no].length() == 0 ) {
662                                        isError = true;
663                                        String label = dbClms[no].getLabel();
664                                        // ERR0012 : 指定のデータがセットされていません。(NULLエラー)。key={0}
665                                        errMsg.addMessage( row+1,ErrorMessage.NG,"ERR0012",label );
666                                }
667                        }
668
669                        // 5.5.7.2 (2012/10/09) エラー時のデバッグ出力
670                        if( isDebug() && isError ) {
671                                errMsg.addMessage( row+1,ErrorMessage.OK,"Debug Info",java.util.Arrays.toString(table.getValues(row) ) );
672                        }
673
674                        // adjustColumns 処理結果を反映させます。
675                        if( useAdjust && !isError ) { table.setValues( vals,row ); }
676                        if( errMsg.size() > ERROR_ROW_COUNT ) { break; }
677                }
678
679                return errMsg;
680        }
681
682        /**
683         * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
684         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
685         *
686         * @og.tag
687         * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に
688         * 渡す場合に、通常は、session を利用します。その場合の登録キーです。
689         * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、
690         * この tableId 属性を利用して、メモリ空間を分けます。
691         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
692         *
693         * @param       id sessionに登録する時の ID
694         */
695        public void setTableId( final String id ) {
696                tableId = nval( getRequestParameter( id ), tableId );
697        }
698
699        /**
700         * 【TAG】可変長ファイルを作成するときの項目区切り文字をセットします。
701         *
702         * @og.tag 可変長ファイルを作成するときの項目区切り文字をセットします。
703         *
704         * @param   separator 項目区切り文字
705         */
706        public void setSeparator( final String separator ) {
707                this.separator = nval( getRequestParameter( separator ),this.separator );
708        }
709
710        /**
711         * 【TAG】読み取り元ディレクトリ名を指定します
712         *              (初期値:FILE_URL[={@og.value org.opengion.hayabusa.common.SystemData#FILE_URL}])。
713         *
714         * @og.tag
715         * この属性で指定されるディレクトリより、ファイルを読み取ります。
716         * 指定方法は、通常の fileURL 属性と同様に、先頭が、'/' (UNIX) または、2文字目が、
717         * ":" (Windows)の場合は、指定のURLそのままのディレクトリに、そうでない場合は、
718         * fileURL = "{&#064;USER.ID}" と指定すると、FILE_URL 属性で指定のフォルダの下に、
719         * さらに、各個人ID別のフォルダを作成して、そこを操作します。
720         * (初期値:システム定数のFILE_URL[={@og.value org.opengion.hayabusa.common.SystemData#FILE_URL}])。
721         *
722         * @og.rev 4.0.0.0 (2005/01/31) StringUtil.urlAppend メソッドの利用
723         * @og.rev 4.0.0.0 (2007/11/20) 指定されたディレクトリ名の最後が"\"or"/"で終わっていない場合に、"/"を付加する。
724         *
725         * @param       url 読み取り元ディレクトリ名
726         * @see         org.opengion.hayabusa.common.SystemData#FILE_URL
727         */
728        public void setFileURL( final String url ) {
729                String furl = nval( getRequestParameter( url ),null );
730                if( furl != null ) {
731                        char ch = furl.charAt( furl.length()-1 );
732                        if( ch != '/' && ch != '\\' ) { furl = furl + "/"; }
733                        fileURL = StringUtil.urlAppend( fileURL,furl );
734                }
735        }
736
737        /**
738         * 【TAG】ファイルを作成するときのファイル名をセットします
739         *              (初期値:FILE_FILENAME[={@og.value org.opengion.hayabusa.common.SystemData#FILE_FILENAME}])。
740         *
741         * @og.tag ファイルを作成するときのファイル名をセットします。
742         * (初期値:システム定数のFILE_FILENAME[={@og.value org.opengion.hayabusa.common.SystemData#FILE_FILENAME}])。
743         *
744         * @param   filename ファイル名
745         * @see         org.opengion.hayabusa.common.SystemData#USE_SQL_INJECTION_CHECK
746         */
747        public void setFilename( final String filename ) {
748                this.filename = nval( getRequestParameter( filename ),this.filename );
749        }
750
751        /**
752         * 【TAG】ファイルを作成するときのファイルエンコーディング名をセットします
753         *              (初期値:FILE_ENCODE[={@og.value org.opengion.hayabusa.common.SystemData#FILE_ENCODE}])。
754         *
755         * @og.tag
756         * Shift_JIS,MS932,Windows-31J,UTF-8,ISO-8859-1,UnicodeLittle
757         * (初期値:システム定数のFILE_ENCODE[={@og.value org.opengion.hayabusa.common.SystemData#FILE_ENCODE}])。
758         *
759         * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更
760         * @og.rev 3.1.3.0 (2003/04/10) FILE_ENCODE から、エンコード情報を取得する。
761         *
762         * @param   enc ファイルエンコーディング名
763         * @see     <a href="http://www.iana.org/assignments/character-sets">IANA Charset Registry</a>
764         * @see         org.opengion.hayabusa.common.SystemData#FILE_ENCODE
765         */
766        public void setEncode( final String enc ) {
767                encode = nval( getRequestParameter( enc ),encode );
768        }
769
770        /**
771         * 【TAG】実際に読み出すクラス名の略称(TableReader_**** の ****)をセットします({@og.doc03Link readerClass 初期値:Default})。
772         *
773         * @og.tag
774         * 実際に読み出すクラス名(の略称)をセットします。
775         * これは、org.opengion.hayabusa.io 以下の TableReader_**** クラスの **** を
776         * 与えます。これらは、TableReader インターフェースを継承したサブクラスです。
777         * 属性クラス定義の {@link org.opengion.hayabusa.io.TableReader TableReader} を参照願います。
778         * {@og.doc03Link readerClass TableReader_**** クラス}
779         *
780         * @param   readerClass クラス名(の略称)
781         * @see         org.opengion.hayabusa.io.TableReader  TableReaderのサブクラス
782         */
783        public void setReaderClass( final String readerClass ) {
784                this.readerClass = nval( getRequestParameter( readerClass ),this.readerClass );
785        }
786
787        /**
788         * 【TAG】読取時の最大取り込み件数をセットします
789         *              (初期値:DB_MAX_ROW_COUNT[={@og.value org.opengion.hayabusa.common.SystemData#DB_MAX_ROW_COUNT}])。
790         *
791         * @og.tag
792         * DBTableModelのデータとして登録する最大件数をこの値に設定します。
793         * サーバーのメモリ資源と応答時間の確保の為です。
794         * 0 をセットすると、無制限(Integer.MAX_VALUE)になります。
795         * (初期値:ユーザー定数のDB_MAX_ROW_COUNT[={@og.value org.opengion.hayabusa.common.SystemData#DB_MAX_ROW_COUNT}])。
796         *
797         * @og.rev 5.5.8.5 (2012/11/27) 0を無制限として処理します。
798         *
799         * @param   count 読取時の最大取り込み件数
800         * @see         org.opengion.hayabusa.common.SystemData#DB_MAX_ROW_COUNT
801         */
802        public void setMaxRowCount( final String count ) {
803                maxRowCount = nval( getRequestParameter( count ),maxRowCount );
804                if( maxRowCount == 0 ) { maxRowCount = Integer.MAX_VALUE ; }            // 5.5.8.5 (2012/11/27)
805        }
806
807        /**
808         * 【TAG】コマンド(NEW,RENEW)をセットします(初期値:NEW)。
809         *
810         * @og.tag
811         * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
812         * フィールド定数値のいづれかを、指定できます。
813         * 何も設定されない、または、null の場合は、"NEW" が初期値にセットされます。
814         *
815         * @param       cmd コマンド(public static final 宣言されている文字列)
816         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.ReadTableTag.CMD_NEW">コマンド定数</a>
817         */
818        public void setCommand( final String cmd ) {
819                String cmd2 = getRequestParameter( cmd );
820                if( cmd2 != null && cmd2.length() > 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); }
821        }
822
823        /**
824         * 【TAG】query の結果を画面上に表示するメッセージIDを指定します(初期値:MSG0033[ 件検索しました])。
825         *
826         * @og.tag
827         * ここでは、検索結果の件数や登録された件数をまず出力し、
828         * その次に、ここで指定したメッセージをリソースから取得して
829         * 表示します。
830         * 表示させたくない場合は, displayMsg = "" をセットしてください。
831         * 初期値は、検索件数を表示します。
832         *
833         * @param   id ディスプレイに表示させるメッセージ ID
834         */
835        public void setDisplayMsg( final String id ) {
836                if( id != null ) { displayMsg = id; }
837        }
838
839        /**
840         * 【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした])。
841         *
842         * @og.tag
843         * ここでは、検索結果がゼロ件の場合のみ、特別なメッセージを表示させます。
844         * 従来は、displayMsg と兼用で、『0 件検索しました』という表示でしたが、
845         * displayMsg の初期表示は、OFF になりましたので、ゼロ件の場合のみ別に表示させます。
846         * 表示させたくない場合は, notfoundMsg = "" をセットしてください。
847         * 初期値は、MSG0077[対象データはありませんでした]です。
848         *
849         * @param       id ディスプレイに表示させるメッセージ ID
850         */
851        public void setNotfoundMsg( final String id ) {
852                String ids = getRequestParameter( id );
853                if( ids != null ) { notfoundMsg = ids; }
854        }
855
856        /**
857         * 【TAG】ファイル取り込み時の モディファイタイプ(A(追加),C(更新),D(削除))を指定します。
858         *
859         * @og.tag
860         * ファイル読み込み時に、そのデータをA(追加)、C(更新)、D(削除)の
861         * モディファイタイプをつけた状態にします。
862         * その状態で、そのまま、update する事が可能になります。
863         *
864         * @param   type ファイル取り込み時の モディファイタイプ(A,C,D属性)
865         */
866        public void setModifyType( final String type ) {
867                modifyType = getRequestParameter( type );
868        }
869
870        /**
871         * 【TAG】EXCELファイルを読み込むときのシート名を設定します(初期値:指定なし)。
872         *
873         * @og.tag
874         * EXCELファイルを読み込む時に、シート名を指定します。これにより、複数の形式の
875         * 異なるデータを順次読み込むことや、シートを指定して読み取ることが可能になります。
876         * sheetNos と sheetName が同時に指定された場合は、sheetNos が優先されます。エラーにはならないのでご注意ください。
877         * 初期値は、指定なしです。
878         *
879         * @og.rev 3.5.4.2 (2003/12/15) 新規追加
880         *
881         * @param   sheet EXCELファイルのシート名
882         * @see         #setSheetNos( String )
883         */
884        public void setSheetName( final String sheet ) {
885                sheetName = nval( getRequestParameter( sheet ),sheetName );
886        }
887
888        /**
889         * 【TAG】EXCELファイルを読み込むときのシート番号を指定します(初期値:0)。
890         *
891         * @og.tag
892         * EXCEL読み込み時に複数シートをマージして取り込みます。
893         * シート番号は、0 から始まる数字で表します。
894         * ヘッダーは、最初のシートのカラム位置に合わせます。(ヘッダータイトルの自動認識はありません。)
895         * よって、指定するシートは、すべて同一レイアウトでないと取り込み時にカラムのずれが発生します。
896         *
897         * シート番号の指定は、カンマ区切りで、複数指定できます。また、N-M の様にハイフンで繋げることで、
898         * N 番から、M 番のシート範囲を一括指定可能です。また、"*" による、全シート指定が可能です。
899         * これらの組み合わせも可能です。( 0,1,3,5-8,10-* )
900         * ただし、"*" に関しては例外的に、一文字だけで、すべてのシートを表すか、N-* を最後に指定するかの
901         * どちらかです。途中には、"*" は、現れません。
902         * シート番号は、重複(1,1,2,2)、逆転(3,2,1) での指定が可能です。これは、その指定順で、読み込まれます。
903         * sheetNos と sheetName が同時に指定された場合は、sheetNos が優先されます。エラーにはならないのでご注意ください。
904         *
905         * 初期値は、0(第一シート) です。
906         *
907         * @og.rev 5.5.7.2 (2012/10/09) 新規追加
908         *
909         * @param   sheet EXCELファイルのシート番号(0から始まる)
910         * @see         #setSheetName( String )
911         */
912        public void setSheetNos( final String sheet ) {
913                sheetNos = nval( getRequestParameter( sheet ),sheetNos );
914                if( sheetNos != null && sheetNos.length() > 0 ) {
915                        boolean errFlag = false;
916                        for( int i=0; i<sheetNos.length(); i++ ) {
917                                char ch = sheetNos.charAt(i);
918                                if( ch == '-' || ch == ',' ) { continue; }
919                                if( ch == '*' && ( i==0 || i==sheetNos.length()-1 ) ) { continue; }
920                                if( ch < '0' || ch > '9' ) { errFlag = true; break; }
921                        }
922                        if( errFlag ) {
923                                String errMsg = "sheetNos の指定を見直してください。sheetNos=[" + sheetNos + "]";
924                                throw new HybsSystemException( errMsg );
925                        }
926                }
927        }
928
929        /**
930         * 【TAG】EXCELファイルを読み込むときのシート単位の固定値を設定するためのカラム名を指定します。
931         *
932         * @og.tag
933         * カラム名は、カンマ区切りで指定します。
934         * これにより、シートの一か所に書かれている情報を、DBTableModel のカラムに固定値として
935         * 設定することができます。
936         * 例として、DB定義書で、テーブル名をシートの全レコードに設定したい場合などに使います。
937         * このメソッドは、isExcel() == true の場合のみ利用されます。
938         *
939         * @og.rev 5.5.8.2 (2012/11/09) 新規追加
940         *
941         * @param   constKeys 固定値となるカラム名(CSV形式)
942         * @see         #setSheetConstAdrs( String )
943         */
944        public void setSheetConstKeys( final String constKeys ) {
945                sheetConstKeys = nval( getRequestParameter( constKeys ),null );
946        }
947
948        /**
949         * 【TAG】EXCELファイルを読み込むときのシート単位の固定値を設定するためのカラム名に対応するアドレスを指定します。
950         *
951         * @og.tag
952         * アドレスは、EXCEL上の行-列をカンマ区切りで指定します。
953         * 行列は、EXCELオブジェクトに準拠するため、0から始まる整数です。
954         * 0-0 ⇒ A1 , 1-0 ⇒ A2 , 0-1 ⇒ B1 になります。
955         * これにより、シートの一か所に書かれている情報を、DBTableModel のカラムに固定値として
956         * 設定することができます。
957         * 例として、DB定義書で、テーブル名をシートの全レコードに設定したい場合などに使います。
958         * このメソッドは、isExcel() == true の場合のみ利用されます。
959         *
960         * 5.7.6.3 (2014/05/23) より、
961         *   @EXCEL表記に準拠した、A1,A2,B1 の記述も処理できるように対応します。
962         *     なお、A1,A2,B1 の記述は、必ず、英字1文字+数字 にしてください。(A〜Zまで)
963         *   A処理中のEXCELシート名をカラムに割り当てるために、"SHEET" という記号に対応します。
964         * 例えば、sheetConstKeys="CLM,LANG,NAME" とし、sheetConstAdrs="0-0,A2,SHEET" とすると、
965         * NAMEカラムには、シート名を読み込むことができます。
966         * これは、内部処理の簡素化のためです。
967         *
968         * ちなみに、EXCELのセルに、シート名を表示させる場合の関数は、下記の様になります。
969         * =RIGHT(CELL("filename",$A$1),LEN(CELL("filename",$A$1))-FIND("]",CELL("filename",$A$1)))
970         *
971         * @og.rev 5.5.8.2 (2012/11/09) 新規追加
972         *
973         * @param   constAdrs 固定値となるアドレス(行-列,行-列,・・・)
974         * @see         #setSheetConstKeys( String )
975         */
976        public void setSheetConstAdrs( final String constAdrs ) {
977                sheetConstAdrs = nval( getRequestParameter( constAdrs ),null );
978        }
979
980        /**
981         * 【TAG】ここに指定されたカラム列に NULL が現れた時点で読み取りを中止します。
982         *
983         * @og.tag
984         * これは、指定のカラムは必須という事を条件に、そのレコードだけを読み取る処理を行います。
985         * 複数Sheetの場合は、次のSheetを読みます。
986         * 現時点では、Excel の場合のみ有効です。
987         *
988         * @og.rev 5.5.8.2 (2012/11/09) 新規追加
989         *
990         * @param   clm カラム列
991         */
992        public void setNullBreakClm( final String clm ) {
993                nullBreakClm = nval( getRequestParameter( clm ),null );
994        }
995
996        /**
997         * 【TAG】読み取り元ファイルのカラム列を、外部(タグ)より指定します。
998         *
999         * @og.tag
1000         * 読み取り元ファイルのカラム列を、外部(タグ)より指定します。
1001         * ファイルに記述された #NAME より優先して使用されます。
1002         * これは、元ファイルのカラムを順番に指定のカラム名に割り当てる機能で
1003         * ファイルの特定のカラム列を抜き出して取り込む機能ではありません。
1004         *
1005         * @og.rev 3.5.4.5 (2004/01/23) 新規作成
1006         *
1007         * @param   clms 読み取り元ファイルのカラム列(カンマ区切り文字)
1008         */
1009        public void setColumns( final String clms ) {
1010                columns = nval( getRequestParameter( clms ),columns );
1011        }
1012
1013        /**
1014         * 【TAG】読み取り元ファイルの整合性チェックを行うカラム列をカンマ指定します。
1015         *
1016         * @og.tag
1017         * カラムオブジェクトのDBType属性に対応したチェックを行います。
1018         * 指定のカラム名をカンマ区切り(CSV)で複数指定できます。
1019         * 全てのカラムのチェックを行う場合は、allColumnCheck = "true" を
1020         * 指定して下さい。
1021         * 分解方法は、通常のパラメータ取得後に、CSV分解します。
1022         *
1023         * @og.rev 3.6.0.2 (2004/10/04) 新規追加 取り込み時チェック用
1024         * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。
1025         *
1026         * @param   clms 整合性チェックを行うカラム列(カンマ区切り文字)
1027         */
1028        public void setCheckColumns( final String clms ) {
1029                checkColumns = nval( getRequestParameter( clms ),checkColumns );
1030        }
1031
1032        /**
1033         * 【TAG】読み取り元ファイルのデータ変換を行うカラム列をカンマ指定します。
1034         *
1035         * @og.tag
1036         * カラムオブジェクトのDBType属性に対応したデータ変換を行います。
1037         * 指定のカラム名をカンマ区切り(CSV)で複数指定できます。
1038         * 分解方法は、通常のパラメータ取得後に、CSV分解します。
1039         *
1040         * @og.rev 3.6.0.2 (2004/10/04) 新規追加 取り込み時データ変換
1041         * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。
1042         *
1043         * @param   clms データ変換を行うカラム列(カンマ区切り文字)
1044         */
1045        public void setAdjustColumns( final String clms ) {
1046                adjustColumns = nval( getRequestParameter( clms ),adjustColumns );
1047        }
1048
1049        /**
1050         * 【TAG】NULL チェックすべきカラム列をカンマ区切り(CVS形式)で指定します。
1051         *
1052         * @og.tag nullCheck="AAA,BBB,CCC,DDD"
1053         * 分解方法は、通常のパラメータ取得後に、CSV分解します。
1054         *
1055         * @og.rev 3.8.0.2 (2005/06/30) 新規追加
1056         * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。
1057         *
1058         * @param   clms カラム列(CVS形式)
1059         */
1060        public void setNullCheck( final String clms ) {
1061                nullCheck = nval( getRequestParameter( clms ),nullCheck );
1062        }
1063
1064        /**
1065         * 【TAG】行番号情報を、使用している/していない[true/false]を指定します(初期値:true)。
1066         *
1067         * @og.tag
1068         * 通常のフォーマットでは、各行の先頭に行番号が出力されています。
1069         * 読み取り時に、#NAME 属性を使用する場合は、この行番号を無視しています。
1070         * #NAME 属性を使用せず、columns 属性でカラム名を指定する場合(他システムの
1071         * 出力ファイルを読み取るケース等)では、行番号も存在しないケースがあり、
1072         * その様な場合に、useNumber="false" を指定すれば、データの最初から読み取り始めます。
1073         * この場合、出力データのカラムの並び順が変更された場合、columns 属性も
1074         * 指定しなおす必要がありますので、できるだけ、#NAME 属性を使用するように
1075         * してください。
1076         * なお、EXCEL 入力には、この設定は適用されません。(暫定対応)
1077         * 初期値は、true(使用する) です。
1078         *
1079         * @og.rev 3.7.0.5 (2005/04/11) 新規追加
1080         *
1081         * @param   useNo 行番号情報 [true:使用する/false:使用しない]
1082         */
1083        public void setUseNumber( final String useNo ) {
1084                useNumber = nval( getRequestParameter( useNo ),useNumber );
1085        }
1086
1087        /**
1088         * 【TAG】読込件数が0件のとき処理を続行するかどうか[true/false]を指定します(初期値:false[続行する])。
1089         *
1090         * @og.tag
1091         * 初期値は、false(続行する)です。
1092         *
1093         * @og.rev 4.3.7.0 (2009/06/01) 新規追加
1094         *
1095         * @param  cmd 読込件数が0件のとき、処理を [true:中止する/false:続行する]
1096         */
1097        public void setStopZero( final String cmd ) {
1098                stopZero = nval( getRequestParameter( cmd ), stopZero );
1099        }
1100
1101        /**
1102         * 【TAG】(通常使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:false)。
1103         *
1104         * @og.tag
1105         * この値は、ファイルダウンロード処理に影響します。この値がtrueに指定された時にcommitされたDBTableModelが
1106         * ファイルダウンロードの対象の表になります。
1107         *
1108         * このパラメーターは、通常、各タグにより実装され、ユーザーが指定する必要はありません。
1109         * 但し、1つのJSP内でDBTableModelが複数生成される場合に、前に処理したDBTableModelについてファイルダウンロードをさせたい
1110         * 場合は、後ろでDBTableModelを生成するタグで、明示的にこの値をfalseに指定することで、ファイルダウンロード処理の対象から
1111         * 除外することができます。
1112         *
1113         * @og.rev 5.1.6.0 (2010/05/01) 新規作成
1114         *
1115         * @param  flag メイントランザクションかどうか
1116         */
1117        public void setMainTrans( final String flag ) {
1118                isMainTrans = nval( getRequestParameter( flag ),isMainTrans );
1119        }
1120
1121        /**
1122         * 【TAG】(通常は使いません)データの読み飛ばし件数を設定します。
1123         *
1124         * @og.tag
1125         * TAB区切りテキストやEXCEL等のデータの読み始めの初期値を指定します。
1126         * ファイルの先頭行が、0行としてカウントしますので、設定値は、読み飛ばす
1127         * 件数になります。(1と指定すると、1件読み飛ばし、2行目から読み込みます。)
1128         * 読み飛ばしは、コメント行などは、無視しますので、実際の行数分読み飛ばします。
1129         * #NAME属性や、columns 属性は、有効です。
1130         *
1131         * @og.rev 5.1.6.0 (2010/05/01) 新規作成
1132         *
1133         * @param       count 読み始めの初期値
1134         */
1135        public void setSkipRowCount( final String count ) {
1136                skipRowCount = nval( getRequestParameter( count ),skipRowCount );
1137        }
1138
1139        /**
1140         * 【TAG】読取処理でラベルをコードリソースに逆変換を行うかどうかを指定します
1141         *              (初期値:USE_TABLE_READER_RENDERER[={@og.value org.opengion.hayabusa.common.SystemData#USE_TABLE_READER_RENDERER}])。
1142         *
1143         * @og.tag
1144         * TableWriter_Renderer 系のクラスで出力した場合は、コードリソースがラベルで出力されます。
1145         * そのファイルを読み取ると、当然、エラーになります。
1146         * ここでは、コードリソースのカラムに対して、ラベルからコードを求める逆変換を行うことで、
1147         * Renderer 系で出力したファイルを取り込むことができるようにします。
1148         *
1149         * ここでは、TableWriter 系と同様に、TableReader_Renderer 系のクラスを作るのではなく、
1150         * 属性値のフラグで、制御します。
1151         * 将来的には、TableWriter 系も廃止して、同様のフラグで制御するように変更する予定です。
1152         * (初期値:システム定数のUSE_TABLE_READER_RENDERER[={@og.value org.opengion.hayabusa.common.SystemData#USE_TABLE_READER_RENDERER}])。
1153         *
1154         * @og.rev 5.2.1.0 (2010/10/01) 新規作成
1155         *
1156         * @param  flag コードリソースのラベル逆変換を行うかどうか
1157         * @see         org.opengion.hayabusa.common.SystemData#USE_TABLE_READER_RENDERER
1158         */
1159        public void setUseRenderer( final String flag ) {
1160                useRenderer = nval( getRequestParameter( flag ),useRenderer );
1161        }
1162
1163        /**
1164         * 【TAG】matchKeysをカンマ区切りで指定します。
1165         *
1166         * @og.tag
1167         * ファイルから特定の行のみを読み取るためのmatchKeysを指定します。
1168         * matchKeysで指定したカラムに対して、matchValsの正規表現でチェックします。
1169         * この機能はTableReader_Defaultのみ有効です。
1170         * 通常は指定する必要はありません。
1171         *
1172         *
1173         * @og.rev 5.9.8.1 (2016/05/13) 新規作成
1174         *
1175         * @param   keys カラム列(カンマ区切り文字)
1176         */
1177        public void setMatchKeys( final String keys ) {
1178                matchKeys = getCSVParameter( keys );
1179
1180                if( matchVals != null && matchKeys.length != matchVals.length ) {
1181                        String errMsg = "matchKeys属性とmatchVals属性の個数が合いません。"
1182                                                + HybsSystem.CR
1183                                                + " matchKeys=[" + matchKeys.length + "]:KEYS="
1184                                                + StringUtil.array2csv( matchKeys ) + HybsSystem.CR
1185                                                + " matchVals=[" + matchVals.length + "]:VLAS="
1186                                                + StringUtil.array2csv( matchVals ) + HybsSystem.CR ;
1187                        throw new HybsSystemException( errMsg );
1188                }
1189        }
1190
1191        /**
1192         * 【TAG】matchKeysをカンマ区切りで指定します。
1193         *
1194         * @og.tag
1195         * ファイルから特定の行のみを読み取るためのmatchKeysを指定します。
1196         * matchKeysで指定したカラムに対して、matchValsの正規表現でチェックします。
1197         * この機能はTableReader_Defaultのみ有効です。
1198         * 通常は指定する必要はありません。
1199         *
1200         *
1201         * @og.rev 5.9.8.1 (2016/05/13) 新規作成
1202         *
1203         * @param   keys カラム列(カンマ区切り文字)
1204         */
1205        public void setMatchVals( final String keys ) {
1206                matchVals = getCSVParameter( keys );
1207
1208                if( matchKeys != null && matchKeys.length != matchVals.length ) {
1209                        String errMsg = "matchKeys属性とmatchVals属性の個数が合いません。"
1210                                                + HybsSystem.CR
1211                                                + " matchKeys=[" + matchKeys.length + "]:KEYS="
1212                                                + StringUtil.array2csv( matchKeys ) + HybsSystem.CR
1213                                                + " matchVals=[" + matchVals.length + "]:VLAS="
1214                                                + StringUtil.array2csv( matchVals ) + HybsSystem.CR ;
1215                        throw new HybsSystemException( errMsg );
1216                }
1217        }
1218
1219        /**
1220         * シリアライズ用のカスタムシリアライズ書き込みメソッド
1221         *
1222         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
1223         * @serialData 一部のオブジェクトは、シリアライズされません。
1224         *
1225         * @param       strm    ObjectOutputStreamオブジェクト
1226         * @throws IOException  入出力エラーが発生した場合
1227         */
1228        private void writeObject( final ObjectOutputStream strm ) throws IOException {
1229                strm.defaultWriteObject();
1230        }
1231
1232        /**
1233         * シリアライズ用のカスタムシリアライズ読み込みメソッド
1234         *
1235         * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
1236         *
1237         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
1238         * @serialData 一部のオブジェクトは、シリアライズされません。
1239         *
1240         * @param       strm    ObjectInputStreamオブジェクト
1241         * @see #release2()
1242         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
1243         * @throws ClassNotFoundException       クラスを見つけることができなかった場合
1244         */
1245        private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
1246                strm.defaultReadObject();
1247        }
1248
1249        /**
1250         * 【TAG】読み取り元ストレージタイプを設定します。
1251         *  
1252         * @og.tag
1253         * ファイルを読み取り元の、ストレージタイプを設定します。
1254         * 未設定の場合は、システムリソースの「CLOUD_TARGET」が参照されます。
1255         * 自身のサーバを指定する場合は、「default」を設定してください。
1256         * 
1257         * @og.rev 5.10.9.0 (2019/03/01) 新規追加
1258         * 
1259         * @param storage 読み取り元ストレージタイプ
1260         */
1261        public void setStorageType( final String storage ) {
1262                storageType = nval( getRequestParameter( storage ), storageType );
1263        }
1264        
1265        /**
1266         * 【TAG】読み取り元バケット名を設定します。
1267         * 
1268         * @og.tag
1269         * ファイルを読み取り元の、バケット名を指定します。
1270         * クラウドストレージ利用時のみ有効です。
1271         * 未設定の場合は、システムリソースの「CLOUD_BUKET」が参照されます。
1272         * 
1273         * @og.rev 5.10.9.0 (2019/03/01) 新規追加
1274         * 
1275         * @param bucket 読み取り元バケット名
1276         */
1277        public void setBucketName( final String bucket ) {
1278                bucketName = nval( getRequestParameter( bucket ), bucketName );
1279        }
1280        
1281        /**
1282         * このオブジェクトの文字列表現を返します。
1283         * 基本的にデバッグ目的に使用します。
1284         *
1285         * @og.rev 5.10.9.0 (2019/03/01) storageType,bucketNameを出力対象に追加。
1286         *
1287         * @return このクラスの文字列表現
1288         */
1289        @Override
1290        public String toString() {
1291                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
1292                                .println( "VERSION"                     ,VERSION        )
1293                                .println( "separator"           ,separator              )
1294                                .println( "fileURL"             ,fileURL                )
1295                                .println( "filename"            ,filename               )
1296                                .println( "encode"                      ,encode                 )
1297                                .println( "readerClass"         ,readerClass    )
1298                                .println( "maxRowCount"         ,maxRowCount    )
1299                                .println( "displayMsg"          ,displayMsg             )
1300                                .println( "executeCount"        ,executeCount   )
1301                                .println( "modifyType"          ,modifyType             )
1302                                .println( "checkColumns"        ,checkColumns   )
1303                                .println( "adjustColumns"       ,adjustColumns  )
1304                                .println( "nullCheck"           ,nullCheck              )
1305                                .println( "command"                     ,command                )
1306                                .println( "tableId"                     ,tableId                )
1307                                .println( "sheetName"           ,sheetName              )
1308                                .println( "sheetNos"            ,sheetNos               )               // 5.5.7.2 (2012/10/09)
1309                                .println( "columns"                     ,columns                )
1310                                .println( "useNumber"           ,useNumber              )
1311                                .println( "storageType"         ,storageType    )
1312                                .println( "bucketName"          ,bucketName             )
1313                                .println( "Other..."    ,getAttributes().getAttribute() )
1314                                .fixForm().toString() ;
1315        }
1316}