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