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