    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.hayabusa.common.HybsSystem;
    019import org.opengion.hayabusa.common.HybsSystemException;
    020import org.opengion.fukurou.util.StringUtil;
    021import org.opengion.fukurou.util.ToString;                                              // 6.1.1.0 (2015/01/17)
    022
    023import static org.opengion.fukurou.util.StringUtil.nval ;
    024
    025import java.util.List;                                                                                  // 6.4.3.2 (2016/02/19)
    026import java.util.ArrayList;                                                                             // 6.9.9.0 (2018/08/20) 新規追加( 5.10.2.1 (2018/08/18) )
    027import java.util.stream.Stream;                                                                 // 6.4.3.2 (2016/02/19)
    028import java.util.stream.Collectors;                                                             // 6.4.3.2 (2016/02/19)
    029
    030/**
    031 * Where句を作成するための条件を指定します｡
    032 *
    033 * このﾀｸﾞのvalue 値に､{&#064;XXXX} 変数が含まれている場合､そのﾘｸｴｽﾄ値が
    034 * ない場合は､このﾀｸﾞそのものがなにも出力しません｡(つまり条件から消えます｡)
    035 * startKeyは､value を連結する場合の頭に置かれる文字列で､where句の最初には表示されず､
    036 * それ以降について､表示されます｡(つまり､where VALUE1 and VALUE2 and VALUE3 … です｡)
    037 * startKey の初期値は､"and" です｡
    038 * multi は､{&#064;XXXX} 変数に､値が複数含まれている場合の処理を規定します｡
    039 * 複数の値とは､同一nameでﾁｪｯｸﾎﾞｯｸｽ指定や､ﾒﾆｭｰでの複数指定した場合､
    040 * ﾘｸｴｽﾄが配列で送られます｡multi="true" とすると､'xx1','xx2','xx3', ･･･ という
    041 * 形式に変換されます｡
    042 * 具体的には､"where PN in ( {&#064;PN} )" という文字列に対して､
    043 * "where PN in ( 'xx1','xx2','xx3' )" を作成することができます｡
    044 * multi の初期値は､"false" です｡
    045 * SystemData の USE_SQL_INJECTION_CHECK が true か､quotCheck 属性が true の場合は､
    046 * ＳＱＬｲﾝｼﾞｪｸｼｮﾝ対策用のｼﾝｸﾞﾙｸｫｰﾄﾁｪｯｸを行います｡ﾘｸｴｽﾄ引数に
    047 * ｼﾝｸﾞﾙｸｫｰﾄ(')が含まれると､ｴﾗｰになります｡
    048 * 同様にUSE_XSS_CHECKがtrueか､xssCheck属性がtrueの場合は､
    049 * ｸﾛｽｻｲﾄｽｽｸﾘﾌﾟﾃｨﾝｸﾞ(XSS)対策のためless/greater than signのﾁｪｯｸを行います｡
    050 *
    051 * 各属性は､{&#064;XXXX} 変数が使用できます｡
    052 * これは､ServletRequest から､XXXX をｷｰに値を取り出し、この変数に割り当てます｡
    053 * つまり､このXXXXをｷｰにﾘｸｴｽﾄすれば､この変数に値をｾｯﾄすることができます｡
    054 *
    055 * @og.formSample
    056 * ●形式：&lt;og:and startKey="[and|or|…]" value="…" multi="[false|true]" /&gt;
    057 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し､{&#064;XXXX} を解析します)
    058 *
    059 * ●Tag定義：
    060 *   &lt;og:and
    061 *       startKey           【TAG】SQL条件句の最初の演算子を指定します(初期値:and)
    062 *       value              【TAG】条件の値を ｾｯﾄします
    063 *       multi              【TAG】複数の引数に対して処理するかどうか[true/false]を設定します(初期値:false)
    064 *       separator          【TAG】multi ｱｸｼｮﾝ時の文字列を分割する項目区切り文字をｾｯﾄします
    065 *       instrVals          【TAG】ｽﾍﾟｰｽで区切られた複数の値すべてを含む条件を作成します
    066 *       instrType          【TAG】instrValsで複数の値を条件にする際の方法を指定します[and,or,andX,orX,in,notin](初期値:and)
    067 *       range              【TAG】数値型ｶﾗﾑに対して､ﾊｲﾌﾝで範囲指定をｶﾝﾏに分解するかどうか[true/false]を設定します(初期値:false) 6.5.0.0 (2016/09/30)
    068 * <del> placeHolder        【TAG】value の?に設定する値を指定します｡(queryType="JDBCPrepared"専用) 8.0.0.0 </del>
    069 *       bindVal            【TAG】value の?に設定する値を指定します｡(queryType="JDBCPrepared"専用 旧placeHolder)
    070 *       quotCheck          【TAG】ﾘｸｴｽﾄ情報の ｼﾝｸﾞﾙｸｫｰﾄ(') 存在ﾁｪｯｸを実施するかどうか[true/false]を設定します (初期値:USE_SQL_INJECTION_CHECK[=true])
    071 *       xssCheck           【TAG】ﾘｸｴｽﾄ情報の HTMLTag開始/終了文字(&gt;&lt;) 存在ﾁｪｯｸを実施するかどうか[true/false]を設定します (初期値:USE_XSS_CHECK[=true])
    072 *       caseKey            【TAG】このﾀｸﾞ自体を利用するかどうかの条件ｷｰを指定します(初期値:null)
    073 *       caseVal            【TAG】このﾀｸﾞ自体を利用するかどうかの条件値を指定します(初期値:null)
    074 *       caseNN             【TAG】指定の値が､null/ｾﾞﾛ文字列 でない場合(Not Null=NN)は､このﾀｸﾞは使用されます(初期値:判定しない)
    075 *       caseNull           【TAG】指定の値が､null/ｾﾞﾛ文字列 の場合は､このﾀｸﾞは使用されます(初期値:判定しない)
    076 *       caseIf             【TAG】指定の値が､true/TRUE文字列の場合は､このﾀｸﾞは使用されます(初期値:判定しない)
    077 *       debug              【TAG】ﾃﾞﾊﾞｯｸﾞ情報を出力するかどうか[true/false]を指定します(初期値:false)
    078 *   &gt;   ... Body ...
    079 *   &lt;/og:and&gt;
    080 *
    081 * ●使用例
    082 *     &lt;og:query command="NEW"&gt;
    083 *             select PN,YOBI,NMEN,HINM from XX01
    084 *         &lt;og:where&gt;
    085 *             &lt;og:and value="PN   =    '{&#064;PN}'"    /&gt;
    086 *             &lt;og:and value="YOBI like '{&#064;YOBI}%'" /&gt;
    087 *         &lt;/og:where&gt;
    088 *             order by PN
    089 *     &lt;/og:query&gt;
    090 *
    091 *          ･検索条件が入力された時(PN=AAA , YOBI=BBB)
    092 *            作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 where PN = 'AAA' and YOBI like 'BBB%' order by PN
    093 *
    094 *          ･検索条件が片方入力されなかった時(PNがNULLのとき、YOBI=BBB)
    095 *            作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 where YOBI like 'BBB%' order by PN
    096 *
    097 *          ･検索条件が入力されなかった時(PNがNULL, YOBIがNULL) WHERE句がなくなる｡
    098 *            作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 order by PN
    099 *
    100 *        注意:WhereTagを使わない場合に､検索条件が入力されなかった場合は､下記のようになります｡
    101 *            select PN,YOBI,NMEN,HINM from XX01 where PN = '' and YOBI like '%' order by PN
    102 *
    103 *    --------------------------------------------------------------------------------------------------------------
    104 *
    105 *     &lt;og:query command="NEW"&gt;
    106 *             select PN,YOBI,NMEN,HINM from XX01 where PN="11111"
    107 *         &lt;og:where startKey="and"&gt;
    108 *             &lt;og:and value="YOBI in   ({&#064;YOBI})" multi="true" /&gt;
    109 *             &lt;og:and value="HINM like '{&#064;HINM}%'"             /&gt;
    110 *         &lt;/og:where&gt;
    111 *             order by PN
    112 *     &lt;/og:query&gt;
    113 *
    114 *          ･YOBI を複数選択し､in で検索する時(YOBI=AA,BB,CC を選択)
    115 *            作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 where PN = '11111'
    116 *                             and YOBI in ( 'AA','BB','CC' ) and HINM like 'BBB%' order by PN
    117 *
    118 *    --------------------------------------------------------------------------------------------------------------
    119 *    bindVal(旧 placeHolder)を利用する場合の利用例｡
    120 *    queryﾀｸﾞのqueryTypeはJDBCPrepared専用です｡
    121 *    なお､multi 使用時は､ﾊﾞｲﾝﾄﾞ変数は､一つのみ指定可能です｡
    122 *
    123 *      &lt;og:query command="NEW" queryType="JDBCPrepared"&gt;
    124 *          SELECT * FROM XX01
    125 *          &lt;og:where&gt;
    126 *              &lt;og:and value="K01 = ?" bindVal="{&#064;VAL1}" /&gt;
    127 *              &lt;og:and value="K02 LIKE ?" bindVal="{&#064;VAL2}%" /&gt;
    128 *              &lt;og:and value="K03 IN (?)" multi="true" bindVal="{&#064;VAL3}" /&gt;
    129 *              &lt;og:and value="K04 = ? || ?" bindVal="{&#064;VAL4},{&#064;VAL5}" /&gt;
    130 *          &lt;/og:where&gt;
    131 *      &lt;/og:query&gt;
    132 *
    133 * @og.group 画面部品
    134 *
    135 * @version  4.0
    136 * @author       Kazuhiko Hasegawa
    137 * @since    JDK5.0,
    138 */
    139public class SqlAndTag extends CommonTagSupport {
    140        /** このﾌﾟﾛｸﾞﾗﾑのVERSION文字列を設定します｡ {@value} */
    141        private static final String VERSION = "8.4.2.1 (2023/03/10)" ;
    142        private static final long serialVersionUID = 842120230310L ;
    143
    144        private String  startKey        = "and";
    145        private String  value           = "";
    146        private String  instrVals       ;                       // 3.8.8.1 (2007/01/06)
    147        private String  instrType       = "and";        // 5.4.1.0 (2011/11/01)
    148        private boolean multi           ;
    149        private boolean quotCheck       = HybsSystem.sysBool( "USE_SQL_INJECTION_CHECK" );      // 4.0.0 (2005/08/31)
    150        private boolean xssCheck        = HybsSystem.sysBool( "USE_XSS_CHECK" );                        // 5.0.0.2 (2009/09/15)
    151        private boolean range           ;                       // 6.5.0.0 (2016/09/30) 数値型ｶﾗﾑの範囲指定(range)の追加｡
    152
    153        private boolean allNull         ;                       // 5.0.0.2 (2009/09/15)
    154        private boolean localReq        ;                       // 6.1.1.0 (2015/01/17) このｸﾗｽの getRequestValue を呼び出すｷｰ
    155
    156        private String  separator       ;                       // 5.2.2.0 (2010/11/01) 項目区切り文字
    157
    158//      private String  placeHolder     ;                       // 5.10.2.1 (2018/08/18)  8.0.0.0 (2021/07/31) 紛らわしい名前なので変更
    159        private String  bindVal ;                               // 8.0.0.0 (2021/07/31)
    160
    161        /**
    162         * ﾃﾞﾌｫﾙﾄｺﾝｽﾄﾗｸﾀｰ
    163         *
    164         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
    165         */
    166        public SqlAndTag() { super(); }         // これも､自動的に呼ばれるが､空のﾒｿｯﾄﾞを作成すると警告されるので､明示的にしておきます｡
    167
    168        /**
    169         * Taglibの開始ﾀｸﾞが見つかったときに処理する doStartTag() を ｵｰﾊﾞｰﾗｲﾄﾞします｡
    170         *
    171         * @og.rev 4.0.0.0 (2006/12/05) BODY 部の値を value に使用する機能追加
    172         * @og.rev 4.0.0.0 (2005/08/31) useQuotCheck() によるＳＱＬｲﾝｼﾞｪｸｼｮﾝ対策
    173         * @og.rev 5.0.0.2 (2009/09/15) XSS対策
    174         * @og.rev 5.2.2.0 (2010/11/01) caseKey ､caseVal 属性対応
    175         * @og.rev 6.1.1.0 (2015/01/17) localReq変数を使う事で､RequestParameter処理を制御します｡
    176         *
    177         * @return      後続処理の指示
    178         */
    179        @Override
    180        public int doStartTag() {
    181                // 5.2.2.0 (2010/11/01) caseKey ､caseVal 属性対応
    182                if( useTag() ) {
    183                        useQuotCheck( quotCheck );
    184                        // 5.0.0.2 (2009/09/15) XSS対策
    185                        useXssCheck( xssCheck );
    186
    187                        localReq = multi;                                               // 6.1.1.0 (2015/01/17) 内部の getRequestValue を呼び出すｷｰ
    188                        value = getRequestParameter( value );
    189
    190                        if( value == null || value.isEmpty() ) {
    191                                return EVAL_BODY_BUFFERED ;     // Body を評価する｡( extends BodyTagSupport 時)
    192                        }
    193
    194        //              if( value != null && value.length() > 0 ) {
    195        //                      return( SKIP_BODY );                    // Body を評価しない
    196        //              }
    197        //              else {
    198        //                      return EVAL_BODY_BUFFERED ;     // Body を評価する｡( extends BodyTagSupport 時)
    199        //              }
    200                }
    201                return SKIP_BODY ;                      // Body を評価しない
    202        }
    203
    204        /**
    205         * Taglibのﾀｸﾞ本体を処理する doAfterBody() を ｵｰﾊﾞｰﾗｲﾄﾞします｡
    206         *
    207         * @og.rev 4.0.0.0 (2006/12/05) BODY 部の値を value に使用する機能追加
    208         * @og.rev 6.1.1.0 (2015/01/17) localReq変数を使う事で､RequestParameter処理を制御します｡
    209         *
    210         * @return      後続処理の指示(SKIP_BODY)
    211         */
    212        @Override
    213        public int doAfterBody() {
    214                localReq = multi;                                               // 6.1.1.0 (2015/01/17) 内部の getRequestValue を呼び出すｷｰ
    215                value = getBodyString();
    216                return SKIP_BODY ;
    217        }
    218
    219        /**
    220         * Taglibの終了ﾀｸﾞが見つかったときに処理する doEndTag() を ｵｰﾊﾞｰﾗｲﾄﾞします｡
    221         *
    222         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応｡release2() を doEndTag()で呼ぶ｡
    223         * @og.rev 3.8.8.1 (2007/01/06) makeInstrVals を加味する｡
    224         * @og.rev 5.0.0.2 (2009/09/15) multi時のallNull対応
    225         * @og.rev 5.1.9.0 (2010/08/01) matchKey ､matchVal 対応 ⇒ 5.2.2.0 (2010/11/01) 廃止
    226         * @og.rev 5.2.2.0 (2010/11/01) caseKey ､caseVal 属性対応
    227         * @og.rev 6.9.9.0 (2018/08/20) placeHolder属性追加( 5.10.2.1 (2018/08/18) )
    228         * @og.rev 8.0.0.0 (2021/07/31) placeHolder属性 → bindVal 名称変更
    229         *
    230         * @return      後続処理の指示
    231         */
    232        @Override
    233        public int doEndTag() {
    234                debugPrint();           // 4.0.0 (2005/02/28)
    235                // 5.2.2.0 (2010/11/01) caseKey ､caseVal 属性対応
    236                if( useTag() ) {
    237                        final SqlWhereTag where = (SqlWhereTag)findAncestorWithClass( this,SqlWhereTag.class );
    238                        if( where == null ) {
    239                                final String errMsg = "<b>" + getTagName() + "ﾀｸﾞは､where ﾀｸﾞの内部におく必要があります｡</b>";
    240                                throw new HybsSystemException( errMsg );
    241                        }
    242
    243                        final boolean useVal = makePlaceHolder();                                       // 6.9.9.0 (2018/08/20) placeHolder属性追加
    244
    245                        // 5.1.9.0 (2010/08/01) matchKey ､matchVal 対応 ⇒ 5.2.2.0 (2010/11/01) 廃止
    246//                      if( ! isNull() && ! allNull ) {                                                         // 5.2.2.0 (2010/11/01)
    247                        if( ! isNull() && ! allNull && useVal ) {                                       // 6.9.9.0 (2018/08/20) placeHolder属性追加
    248                                value = makeInstrVals( instrVals,instrType,value );             // 5.4.1.0 (2011/11/01)
    249                                if( value != null ) {
    250                                        set( "keyWord", startKey );
    251                                        set( "value"  , value );
    252                                        where.setAttributes( getAttributes() );
    253                                }
    254                        }
    255                }
    256                return EVAL_PAGE ;
    257        }
    258
    259        /**
    260         * ﾀｸﾞﾘﾌﾞｵﾌﾞｼﾞｪｸﾄをﾘﾘｰｽします｡
    261         * ｷｬｯｼｭされて再利用されるので､ﾌｨｰﾙﾄﾞの初期設定を行います｡
    262         *
    263         * @og.rev 2.0.0.4 (2002/09/27) ｶｽﾀﾑﾀｸﾞの release() ﾒｿｯﾄﾞを､追加
    264         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応｡release2() を doEndTag()で呼ぶ｡
    265         * @og.rev 3.8.8.1 (2007/01/06) instrVals 属性追加
    266         * @og.rev 4.0.0.0 (2005/08/31) quotCheck 属性の追加
    267         * @og.rev 5.0.0.2 (2009/09/15) XSS対応
    268         * @og.rev 5.0.0.2 (2009/09/15) multi時のallNull対応
    269         * @og.rev 5.1.9.0 (2010/08/01) matchKey､matchVal 属性の追加
    270         * @og.rev 5.2.2.0 (2010/11/01) separator , isMatch 属性の追加
    271         * @og.rev 5.2.2.0 (2010/11/01) matchKey､matchVal 属性廃止(caseKey,caseVal属性を使用してください｡)
    272         * @og.rev 5.4.1.0 (2011/11/01) instrType属性追加
    273         * @og.rev 6.1.1.0 (2015/01/17) localReq変数を使う事で､RequestParameter処理を制御します｡
    274         * @og.rev 6.5.0.0 (2016/09/30) 数値型ｶﾗﾑの範囲指定(range)の追加｡
    275         * @og.rev 6.9.9.0 (2018/08/20) placeHolder属性追加( 5.10.2.1 (2018/08/18) )
    276         * @og.rev 8.0.0.0 (2021/07/31) placeHolder属性 → bindVal 名称変更
    277         */
    278        @Override
    279        protected void release2() {
    280                super.release2();
    281                startKey        = "and";
    282                value           = "";
    283                instrVals       = null;         // 3.8.8.1 (2007/01/06)
    284                instrType       = "and";        // 5.4.1.0 (2011/11/01)
    285                multi           = false;
    286                quotCheck       = HybsSystem.sysBool( "USE_SQL_INJECTION_CHECK" );      // 4.0.0 (2005/08/31)
    287                xssCheck        = HybsSystem.sysBool( "USE_XSS_CHECK" );                        // 5.0.0.2 (2009/09/15)
    288                allNull         = false;        // 5.0.0.2 (2009/09/15)
    289                separator       = null;         // 5.2.2.0 (2010/11/01) 項目区切り文字
    290                localReq        = false;        // 6.1.1.0 (2015/01/17) このｸﾗｽの getRequestValue を呼び出すｷｰ
    291                range           = false;        // 6.5.0.0 (2016/09/30) 数値型ｶﾗﾑの範囲指定(range)の追加｡
    292//              placeHolder     = null;         // 5.10.2.1 (2018/08/18) ﾌﾟﾚｰｽﾎﾙﾀﾞｰ判定用
    293                bindVal         = null;         // 8.0.0.0 (2021/07/31) ﾌﾟﾚｰｽﾎﾙﾀﾞｰ判定用
    294        }
    295
    296        /**
    297         * ﾘｸｴｽﾄ情報の文字列を取得します｡
    298         *
    299         * これは､通常のgetRequestParameter 処理の中で呼ばれる getRequestValue を
    300         * ｵｰﾊﾞｰﾗｲﾄしています｡
    301         *
    302         * @og.rev 5.0.0.2 (2009/09/15) valuesの全NULL/空文字をisNull扱いにする
    303         * @og.rev 5.3.8.0 (2011/08/01) Attribute等からも値が取得できるようにする｡の対応時の特殊処理
    304         * @og.rev 6.1.1.0 (2015/01/17) localReq変数を使う事で､RequestParameter処理を制御します｡
    305         * @og.rev 6.5.0.0 (2016/09/30) 数値型ｶﾗﾑの範囲指定(range)の追加｡
    306         *
    307         * @param    key ｷｰ
    308         *
    309         * @return   ﾘｸｴｽﾄ情報の文字列
    310         */
    311        @Override
    312        protected String getRequestValue( final String key ) {
    313                String rtn = "";
    314
    315                if( localReq ) {                // 6.1.1.0 (2015/01/17) localReq変数を使う
    316                        // 5.3.8.0 (2011/08/01) getRequestValues の中で､getRequestValue を呼び出すためこのままでは
    317                        // 再帰呼び出しが永遠に続くので､２回目以降は､再帰しないように､強制的に multi の値を書き換えます｡
    318                        localReq = false;       // 6.1.1.0 (2015/01/17) 再帰しないように､localReq変数の値を書き換え
    319                        final String[] array = getRequestValues( key );
    320                        allNull = true; // 5.0.0.2 (2009/09/15) arrayの内容が全てnull/空文字か
    321                        if( ! isNull() ) {
    322                                // 5.0.0.2 (2009/09/15) 全てnull/空文字の場合はnullと扱い
    323                                for( int i=0; i<array.length; i++ ) {
    324                                        if( array[i] != null && !array[i].isEmpty() ) {
    325                                                allNull = false;
    326                                                break;
    327                                        }
    328                                }
    329                                if( ! allNull ){
    330                                        rtn = makeCSVvalue( array );
    331                                }
    332                        }
    333                }
    334                else {
    335                        rtn = super.getRequestValue( key );
    336                        // 6.5.0.0 (2016/09/30) 数値型ｶﾗﾑの範囲指定(range)の追加｡
    337                        if( range ) { rtn = makeRangeCsv( rtn ); }
    338                }
    339                return rtn ;
    340        }
    341
    342        /**
    343         * 複数の値を 'xx1','xx2','xx3', ･･･ という形式に変換します｡
    344         *
    345         * この処理は､in などで使用するためのﾘｸｴｽﾄを配列で受け取って処理
    346         * する場合の文字列を加工します｡
    347         *
    348         * @og.rev 5.2.2.0 (2010/11/01) separator 対応
    349         * @og.rev 6.1.1.0 (2015/01/17) 引数が､null や空文字列の場合は､処理しません｡
    350         * @og.rev 6.4.3.2 (2016/02/19) separator で分割後の文字列を trim() しておきます｡
    351         *
    352         * @param       array   元の文字列配列(可変長引数)
    353         *
    354         * @return  連結後の文字列
    355         * @og.rtnNotNull
    356         */
    357        private String makeCSVvalue( final String... array ) {
    358                if( array == null || array.length == 0 ) {
    359                        final String errMsg = "array 引数に､null や､ｻｲｽﾞｾﾞﾛの配列は使用できません｡";
    360                        throw new HybsSystemException( errMsg );
    361                }
    362
    363                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    364
    365                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
    366                if( separator == null ) {
    367                        for( final String val : array ) {
    368                                if( val != null && !val.isEmpty() && !val.trim().isEmpty() ) {
    369                                        // 6.4.3.2 (2016/02/19) append の文字列を trim() しておきます｡
    370                                        buf.append( '\'' ).append( val.trim() ).append( "'," );
    371                                }
    372                        }
    373                }
    374                else {
    375                        for( final String vals : array ) {
    376                                if( vals != null && !vals.isEmpty() && !vals.trim().isEmpty() ) {
    377                                        // 6.4.3.2 (2016/02/19) separator で分割後の文字列を trim() しておきます｡
    378                                        for( final String val : vals.split( separator ) ) {
    379                                                if( val != null && !val.isEmpty() && !val.trim().isEmpty() ) {
    380                                                        buf.append( '\'' ).append( val.trim() ).append( "'," );
    381                                                }
    382                                        }
    383                                }
    384                        }
    385                }
    386
    387                // 6.4.3.2 (2016/02/19) 最後の ﾋﾟﾘｵﾄﾞを削除する｡buf が append されている場合のみ削除する｡
    388                if( buf.length() > 0 ) { buf.deleteCharAt( buf.length()-1 ); }
    389                return buf.toString();
    390        }
    391
    392        /**
    393         * ｽﾍﾟｰｽで区切られた複数の値を and 接続で連結します｡
    394         *
    395         * value="CLM" instrVals="ABC DEF GHI" と指定すると､
    396         * value="CLM LIKE '%ABC%' AND CLM LIKE '%DEF%'  AND CLM LIKE '%GHI%' "
    397         * という文字列を作成します｡
    398         * 個別にLIKE検索項目を AND 連結する為､現れる場所に依存しません｡
    399         * 逆に､現れる順序を指定する場合は､ABC%DEF の様に指定可能です｡
    400         * ただし､columnMarker の instrVals で､複数文字のﾏｰｶｰを行う場合､
    401         * ABC%DEF という文字列は､ｵﾘｼﾞﾅﾙでないので､ﾏｰｸｱｯﾌﾟされません｡
    402         *
    403         * @og.rev 5.4.1.0 (2011/11/01) instrType属性対応
    404         * @og.rev 5.5.1.1 (2012/04/06) notin対応
    405         * @og.rev 6.1.1.0 (2015/01/17) localReq変数を使う事で､RequestParameter処理を制御します｡
    406         * @og.rev 6.1.1.0 (2015/01/17) 分割ｷｰをseparatorで指定可能とします｡
    407         * @og.rev 6.4.3.2 (2016/02/19) 区切り文字を､ｽﾍﾟｰｽ､ｶﾝﾏ､ﾀﾌﾞ､改行にします｡
    408         * @og.rev 6.7.3.0 (2017/01/27) in とnot in のｺｰﾃﾞｨﾝｸﾞを､変更
    409         * @og.rev 6.8.5.0 (2018/01/09) StringUtil.csv2Array のﾃﾞﾌｫﾙﾄﾒｿｯﾄﾞを使用します｡
    410         * @og.rev 8.4.2.1 (2023/03/10) instrType属性に､andX,orX の追加
    411         *
    412         * @param       instrVals       繰返し処理を行う値
    413         * @param       instrType       連結方法
    414         * @param       value           繰返し処理を行うvalue
    415         *
    416         * @return  連結後の文字列
    417         * @see         #setInstrVals( String )
    418         * @see         ColumnMarkerTag#setInstrVals( String )
    419         */
    420        private String makeInstrVals( final String instrVals, final String instrType , final String value ) {
    421                // instrValsが､設定されていない場合は､通常通り､value を使用する｡
    422                if( instrVals == null || instrVals.isEmpty() ) { return value; }
    423
    424                localReq = multi;                                               // 6.1.1.0 (2015/01/17) 内部の getRequestValue を呼び出すｷｰ
    425                // instrValsが､設定されているが､ﾘｸｴｽﾄ変数処理の結果が､null の場合は､このﾀｸﾞを使用しないため､null を返す｡
    426                final String reqVals = nval( getRequestParameter( instrVals ),null );
    427                if( reqVals == null || reqVals.isEmpty() ) { return null; }
    428
    429                // 6.4.3.2 (2016/02/19) empty() のときは処理
    430                final List<String> lst;
    431                if( multi ) {
    432                        // multi のときは､makeCSVvalue で加工された値になっているので､前後の ' はずし が必要｡
    433                        final String[] vals = StringUtil.csv2Array( reqVals );                  // 6.8.5.0 (2018/01/09) ﾃﾞﾌｫﾙﾄがｶﾝﾏ
    434                        lst = Stream.of( vals )
    435                                        .filter( v -> v != null && v.length() > 2 )
    436                                        .map(    v -> v.substring( 1,v.length()-1 ) )
    437                                        .collect( Collectors.toList() );
    438
    439                        // multi のときは､makeCSVvalue で加工された値になっている｡
    440                }
    441                else {
    442                        // 6.4.3.2 (2016/02/19) 区切り文字を､ｽﾍﾟｰｽ､ｶﾝﾏ､ﾀﾌﾞ､改行にします｡
    443                        final String[] vals = reqVals.split( separator == null ? "[, \\t\\n]" : separator );
    444
    445                        if( vals == null || vals.length == 0 ) { return null; }         // splitしているので､nullはありえない･･･はず｡
    446                        else {
    447                                // 6.4.3.2 (2016/02/19) separator で分割後の文字列を trim() しておきます｡
    448                                lst = Stream.of( vals )
    449                                                .filter( v -> v != null && !v.isEmpty() && !v.trim().isEmpty() )
    450                                                .map(    v -> v.trim() )
    451                                                .collect( Collectors.toList() );
    452                        }
    453                }
    454
    455//              // 6.4.3.2 (2016/02/19) 先のif文の else でしか､null はありえないので､上にもって行きます｡
    456//              final char instType = instrType != null && instrType.length() > 0 ? instrType.charAt(0) : 'X' ;
    457
    458                // 6.4.3.2 (2016/02/19) 元より判りにくくなった感じがしますが､とりあえず｡
    459                final String st  ;              // 文字列連結の 先頭文字
    460                final String sep ;              // 連結文字
    461                final String ed  ;              // 最後の連結文字
    462
    463                // 8.4.2.1 (2023/03/10) instrType属性に､andX,orX の追加 と､判定方法の変更
    464//              if( 'a' == instType || 'A' == instType ) {                              // 6.1.1.0 (2015/01/17) 大文字対応
    465                if( "and".equalsIgnoreCase( instrType ) ) {                             // 8.4.2.1 (2023/03/10)
    466                        st  = " ( "     + value + " LIKE '%" ;
    467                        sep = "%' and " + value + " LIKE '%" ;
    468                        ed  = "%' ) " ;
    469                }
    470                // 8.4.2.1 (2023/03/10) 新規追加 前方一致
    471                else if( "andx".equalsIgnoreCase( instrType ) ) {
    472                        st  = " ( "     + value + " LIKE '" ;
    473                        sep = "%' and " + value + " LIKE '" ;
    474                        ed  = "%' ) " ;
    475                }
    476                // 条件:or ⇒ 各値をorのlike条件で結合(%あり)
    477//              else if( 'o' == instType || 'O' == instType ) {                 // 6.1.1.0 (2015/01/17) 大文字対応
    478                else if( "or".equalsIgnoreCase( instrType ) ) {                 // 8.4.2.1 (2023/03/10)
    479                        st  = " ( "    + value + " LIKE '%" ;
    480                        sep = "%' or " + value + " LIKE '%" ;
    481                        ed  = "%' ) " ;
    482                }
    483                // 8.4.2.1 (2023/03/10) 新規追加 前方一致
    484                else if( "orx".equalsIgnoreCase( instrType ) ) {
    485                        st  = " ( "    + value + " LIKE '" ;
    486                        sep = "%' or " + value + " LIKE '" ;
    487                        ed  = "%' ) " ;
    488                }
    489                // 条件:in ⇒ 各値をorのlike条件で結合(%なし)
    490//              else if( 'i' == instType || 'I' == instType ) {                 // 6.1.1.0 (2015/01/17) 大文字対応
    491                else if( "in".equalsIgnoreCase( instrType ) ) {                 // 8.4.2.1 (2023/03/10)
    492                        st  = value + " in ( '" ;
    493                        sep = "','" ;
    494                        ed  = "' ) " ;
    495                }
    496                // 条件:notin ⇒ 各値をandのnot like条件で結合(%なし) 5.5.1.1(2012/04/05)
    497//              else if( 'n' == instType || 'N' == instType ) {                 // 6.1.1.0 (2015/01/17) 大文字対応
    498                else if( "notin".equalsIgnoreCase( instrType ) ) {                      // 8.4.2.1 (2023/03/10)
    499                        st  = value + " not in ( '" ;
    500                        sep = "','" ;
    501                        ed  = "' ) " ;
    502                }
    503                else {
    504//                      final String errMsg = "instrTypeには､'and','or','in','notin'のいずれかを指定して下さい｡" + CR +
    505                        final String errMsg = "instrTypeには､[and,or,andX,orX,in,notin] のいずれかを指定して下さい｡" + CR +
    506                                                                                " instrType=[" + instrType + "]";
    507                        throw new HybsSystemException( errMsg );
    508                }
    509
    510                // null,isEmpty(),trim().isEmpty() 以外の List から､文字列連結して､SQL文を作成します｡
    511                return lst.stream().collect( Collectors.joining( sep , st , ed ) ) ;
    512        }
    513
    514        /**
    515         * 数値型ｶﾗﾑの範囲指定処理を行います｡
    516         *
    517         * 引数に､"1,3,4-8" のような指定を行うと､"1,3,4,5,6,7,8" に変換します｡
    518         * これは､数値ｶﾗﾑの範囲指定で､対象は自然数なので､小数や､ﾏｲﾅｽ､増加ｽﾃｯﾌﾟが１以外､
    519         * ﾏｲﾅｽｽﾃｯﾌﾟは扱えません｡
    520         *
    521         * 数値が前提なので､区切り記号は､ｽﾍﾟｰｽ､ｶﾝﾏで区切ったあと､再度､ｶﾝﾏでつなげます｡
    522         * その際､"-" を含む場合は､前後の数値を､１づつ増加させてｶﾝﾏでつなげます｡
    523         *
    524         * @og.rev 6.5.0.0 (2016/09/30) 数値型ｶﾗﾑの範囲指定(range)の追加｡
    525         *
    526         * @param       inVal 指定の数値型ｶﾗﾑの値
    527         * @return      数値型ｶﾗﾑの範囲指定変換の値
    528         */
    529        private String makeRangeCsv( final String inVal ) {
    530                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    531
    532                for( final String val : inVal.split( "[, ]" ) ) {                       // ｽﾍﾟｰｽ､ｶﾝﾏで分割
    533                        if( val != null && !val.isEmpty() ) {
    534                                final int ad = val.indexOf( '-' );
    535                                if( ad < 0 ) {
    536                                        buf.append( val ).append( ',' );
    537                                }
    538                                else {          // 範囲処理
    539                                        final int st = Integer.parseInt( val.substring( 0,ad ) );
    540                                        final int ed = Integer.parseInt( val.substring( ad+1 ) );
    541                                        for( int i=st; i<=ed; i++ ) {   // 終了条件は含みます｡
    542                                                buf.append( Integer.toString( i ) ).append( ',' );
    543                                        }
    544                                }
    545                        }
    546                }
    547
    548                final int len = buf.length();                           // 長さを取得｡
    549                if( len > 1 ) { buf.setLength( len-1 ); }       // 長さがある場合､最後のｶﾝﾏを削除します｡
    550
    551                return buf.toString();
    552        }
    553
    554        /**
    555         * ﾊﾞｲﾝﾄﾞ変数(ﾌﾟﾚｰｽﾎﾙﾀﾞｰ)の処理を行います｡
    556         *
    557         * bindVal属性から､ﾘｸｴｽﾄ値を取り出し､上位のQueryTagに追記します｡
    558         * multi の場合は､引数は､一つのみとします｡
    559         * 戻り値は､以降の処理を続ける場合は､trueを､そうでない場合は､false を返します｡
    560         * bindVal属性が未設定の場合は､true になります｡また､設定されており､そのﾘｸｴｽﾄ変数も
    561         * 存在する場合も､true になります｡唯一､bindVal属性が設定されており､そのﾘｸｴｽﾄ変数が
    562         * 存在しない場合のみ､false となります｡
    563         *
    564         * @og.rev 6.9.9.0 (2018/08/20) 新規追加( 5.10.2.1 (2018/08/18) )
    565         * @og.rev 8.0.0.0 (2021/07/31) placeHolder属性 → bindVal 名称変更
    566         *
    567         * @return  処理を継続する場合は､true
    568         * @og.rtnNotNull
    569         */
    570        private boolean makePlaceHolder() {
    571                // 6.9.9.0 (2018/08/20) placeHolder属性追加( 5.10.2.1 (2018/08/18) )
    572                // 8.0.0.0 (2021/07/31) placeHolder属性 → bindVal 名称変更
    573                if( StringUtil.isNotNull( bindVal,value ) ) {                                                           // どちらも､null で無ければ､true
    574                        if( value.indexOf( '?' ) < 0 ) {
    575                                final String errMsg = "<b>" + getTagName() + "ﾀｸﾞでbindValを使う場合は､value に､? が必要です｡</b>";
    576                                throw new HybsSystemException( errMsg );
    577                        }
    578
    579                        final QueryTag query = (QueryTag)findAncestorWithClass( this, QueryTag.class);
    580                        if( query == null ) {
    581                                final String errMsg = "<b>" + getTagName() + "ﾀｸﾞでbindValを使う場合は､query ﾀｸﾞの内部におく必要があります｡</b>";
    582                                throw new HybsSystemException( errMsg );
    583                        }
    584
    585                        if( multi ) {
    586                                final int ad = value.indexOf( '?' );
    587
    588                                if( bindVal.indexOf( ',' ) >= 0 || ad != value.lastIndexOf( '?' ) ) {
    589                                        final String errMsg = "<b>" + getTagName() + "ﾀｸﾞでbindValを使う場合は､multi は､引数一つのみ有効です｡</b>";
    590                                        throw new HybsSystemException( errMsg );
    591                                }
    592
    593                                final String[] reqVals = getRequestParameterValues( bindVal );  // {@XXX} を､ﾏﾙﾁﾘｸｴｽﾄ変数処理
    594                                final List<String> tmpLst = new ArrayList<>();
    595                                // "?" を､",?" に置換する｡初期の "?" の位置は､一つだけと制限しています｡
    596                                final StringBuilder tmpVal = new StringBuilder( value );
    597                                boolean second = false;                                                                                         // ２回目以降に､"?" を増やす処理を行います｡
    598                                for( final String phVal : reqVals ) {
    599                                        if( StringUtil.isNotNull( phVal ) ) {
    600                                                tmpLst.add( phVal );                                                                            // ﾏﾙﾁの場合､値がなくても正常
    601                                                if( second ) { tmpVal.insert( ad+1 , ",?" ); }                          // 既存の "?" の次に､",?" を追加します｡
    602                                                second = true;
    603                                        }
    604                                }
    605                                if( tmpLst.isEmpty() ) { return false; }                                                        // 一つも､値が無い場合は､false にして終了
    606
    607                                value = tmpVal.toString();
    608                                tmpLst.forEach( v -> query.addPlaceValue( v ) );
    609                        }
    610                        else {
    611                                final String[] csvVals = getCSVParameter( bindVal );                    // {@XXX} を､CSV形式で分解して､ﾘｸｴｽﾄ変数処理
    612                                if( StringUtil.isNull( csvVals ) ) { return false; }                            // 一つでも､null があれば､false にして終了
    613
    614                                for( final String phVal : csvVals ) {
    615                                        query.addPlaceValue( phVal );
    616                                }
    617                        }
    618                }
    619
    620                return true;
    621        }
    622
    623        /**
    624         * 【TAG】SQL条件句の最初の演算子を指定します(初期値:and)｡
    625         *
    626         * @og.tag
    627         * value を連結する場合の頭に置かれる文字列で､where句の最初には表示されず､
    628         * それ以降について､表示されます｡
    629         * (つまり､where VALUE1 and VALUE2 and VALUE3 … です｡)
    630         * startKey の初期値は､"and" です｡
    631         *
    632         * @og.rev 6.1.1.0 (2015/01/17) localReq変数を使う事で､RequestParameter処理を制御します｡
    633         *
    634         * @param       skey 条件句の最初の演算子
    635         */
    636        public void setStartKey( final String skey ) {
    637                startKey = nval( getRequestParameter( skey ),startKey );                // 6.1.1.0 (2015/01/17)
    638        }
    639
    640        /**
    641         * 【TAG】条件の値を ｾｯﾄします｡
    642         *
    643         * @og.tag
    644         * 条件値に､{&#064;XXXX} 変数が含まれている場合､そのﾘｸｴｽﾄ値がない場合は､
    645         * このﾀｸﾞそのものがなにも出力しません｡(つまり条件から消えます｡)
    646         * BODY 部に記述することが可能です｡その場合は､条件属性になにも設定できません｡
    647         *
    648         * @param       val 条件値
    649         */
    650        public void setValue( final String val ) {
    651                value = val;
    652        }
    653
    654        /**
    655         * 【TAG】特定の文字で区切られた複数の値すべてを含む条件を作成します｡
    656         *
    657         * @og.tag
    658         * value="CLM" instrVals="ABC DEF GHI" と指定すると､
    659         * value="CLM LIKE '%ABC%' AND CLM LIKE '%DEF%'  AND CLM LIKE '%GHI%' "
    660         * という文字列を作成します｡
    661         * 通常の､value="CLM LIKE '%ABC%DEF%'" の指定方法では､ABCとDEFの
    662         * 順番が固定化されますが､instrVals を用いた方法では､個別指定が可能です｡
    663         *
    664         * ※ 6.4.3.2 (2016/02/19)
    665         * これは､instrVals に指定した引数に対して､ｽﾍﾟｰｽ､ｶﾝﾏ､ﾀﾌﾞ､改行の
    666         * どれかで区切ります｡個別に指定する場合は､separatorに設定します｡
    667         * これは､instrVals.split(separator) で分割するので､正規表現が使用可能です｡
    668         * 分割後に､前方の value に複数のAND検索(instrTypeで変更可)を同時に指定できる
    669         * ため､現れる場所に依存しません｡
    670         *
    671         * 逆に､現れる順序を指定する場合は､ABC%DEF の様に指定可能です｡
    672         * ただし､columnMarker の instrVals で､複数文字のﾏｰｶｰを行う場合､
    673         * ABC%DEF という文字列は､ｵﾘｼﾞﾅﾙでないので､ﾏｰｸｱｯﾌﾟされません｡
    674         * ※instrType属性の指定により条件の生成方法を変更することができます｡
    675         *   詳細については､instrType属性のﾄﾞｷｭﾒﾝﾄを参照下さい｡
    676         *
    677         * @og.rev 6.4.3.2 (2016/02/19) 区切り文字を､ｽﾍﾟｰｽ､ｶﾝﾏ､ﾀﾌﾞ､改行にします｡
    678         *
    679         * @param       val 複合条件作成のための設定値
    680         * @see         #setInstrType
    681         * @see         ColumnMarkerTag#setInstrVals( String )
    682         */
    683        public void setInstrVals( final String val ) {
    684                instrVals = val;
    685        }
    686
    687        /**
    688         * 【TAG】instrValsで複数の値を条件にする際の方法を指定します(初期値:and)｡
    689         *
    690         * @og.tag
    691         * 通常､instrValsに指定された値は､ｽﾍﾟｰｽ区切りで分割した各値を
    692         * LIKE条件としてand結合します｡
    693         * しかし､instrType属性を変更することで､この条件式の生成方法を変更
    694         * することができます｡
    695         * 具体的には､以下の通りです｡
    696         * ①instrTypeに"and"が指定されている場合(初期値)
    697         *   ﾀｸﾞの記述 : value="CLM" instrVals="ABC DEF GHI"
    698         *   生成文字列 :       "( CLM LIKE '%ABC%' AND CLM LIKE '%DEF%' AND CLM LIKE '%GHI%' )"
    699         * ②instrTypeに"or"が指定されている場合
    700         *   ﾀｸﾞの記述 : value="CLM" instrVals="ABC DEF GHI"
    701         *   生成文字列 :       "( CLM LIKE '%ABC%' OR CLM LIKE '%DEF%' OR CLM LIKE '%GHI%' )"
    702         * ③instrTypeに"in"が指定されている場合
    703         *   ﾀｸﾞの記述 : value="CLM" instrVals="ABC DEF GHI"
    704         *   生成文字列 :       "CLM in ('ABC','DEF5','GHI')"
    705         * ④instrTypeに"notin"が指定されている場合
    706         *       ﾀｸﾞの記述 : value="CLM" instrVals="ABC DEF GHI"
    707         *   生成文字列 :       "CLM not in ('ABC','DEF5','GHI')"
    708         * ⑤instrTypeに"andX"が指定されている場合(前方一致 and) 8.4.2.1 (2023/03/10) 追加
    709         *   ﾀｸﾞの記述 : value="CLM" instrVals="ABC DEF GHI"
    710         *   生成文字列 :       "( CLM LIKE 'ABC%' AND CLM LIKE 'DEF%' AND CLM LIKE 'GHI%' )"
    711         * ⑥instrTypeに"orX"が指定されている場合(前方一致 or) 8.4.2.1 (2023/03/10) 追加
    712         *   ﾀｸﾞの記述 : value="CLM" instrVals="ABC DEF GHI"
    713         *   生成文字列 :       "( CLM LIKE 'ABC%' OR CLM LIKE 'DEF%' OR CLM LIKE 'GHI%' )"
    714         * ※この属性を指定しない場合は､①のLIKE条件でのand結合となります｡
    715         * <del>※③④について､LIKE条件で%を自動付加しないことにより､画面からの入力値に応じて､
    716         *   前方一致､後方一致､前後方一致の制御を行うことができます｡</del>
    717         *
    718         * @og.rev 5.5.1.1 (2012/04/06) notin対応(ｺﾒﾝﾄ修正)
    719         * @og.rev 6.1.1.0 (2015/01/17) 初期値指定のｺｰﾃﾞｨﾝｸﾞﾐｽ修正
    720         * @og.rev 6.7.3.0 (2017/01/27) in とnot in のｺｰﾃﾞｨﾝｸﾞを､変更
    721         * @og.rev 8.4.2.1 (2023/03/10) instrType属性に､andX,orX の追加
    722         *
    723         * @param       tp 条件方法 [and/or/in/notin]
    724         * @see         #setInstrVals( String )
    725         */
    726        public void setInstrType( final String tp ) {
    727                instrType = nval( getRequestParameter( tp ),instrType );                // 6.1.1.0 (2015/01/17)
    728        }
    729
    730        /**
    731         * 【TAG】複数の引数に対して処理するかどうか[true/false]を設定します(初期値:false)｡
    732         *
    733         * @og.tag
    734         * {&#064;XXXX} 変数に､値が複数含まれている場合の処理を規定します｡
    735         * multi="true" に設定すると､複数の引数は､'xx1','xx2','xx3', ･･･ という
    736         * 形式に変換します｡
    737         * where 条件で言うと､ "where PN in ( {&#064;PN} )" という文字列に対して､
    738         * "where PN in ( 'xx1','xx2','xx3' )" を作成することになります｡
    739         * 初期値は､ false (ﾏﾙﾁ変換しない) です｡
    740         *
    741         * @og.rev 6.1.1.0 (2015/01/17) localReq変数を使う事で､RequestParameter処理を制御します｡
    742         *
    743         * @param   flag ﾏﾙﾁ変換 [true:する/それ以外:しない]
    744         * @see         #setSeparator( String )
    745         */
    746        public void setMulti( final String flag ) {
    747                multi = nval( getRequestParameter( flag ),multi );
    748        }
    749
    750        /**
    751         * 【TAG】multi ｱｸｼｮﾝ/instrVals 時の文字列を分割する項目区切り文字をｾｯﾄします｡
    752         *
    753         * @og.tag
    754         * multi="true" の場合､複数のﾘｸｴｽﾄを連結して､in 句で問合せを行う文字列を
    755         * 作成しますが､separator を指定すると､さらに､separator で文字列を分割して､
    756         * in 句の引数を構築します｡
    757         * これは､instrVals を指定した場合にも､同様に分解します｡
    758         * 具体的には､分割後の文字列が､複数の個々のﾘｸｴｽﾄ変数と同じ形式に加工されます｡
    759         * String#split( separator ) で､分解するため､正規表現が使用できます｡
    760         *
    761         * 何も指定しない場合は､multi ｱｸｼｮﾝ時は､分割処理は行いません｡
    762         * instrVals 時は､ｽﾍﾟｰｽで分解処理します｡
    763         *
    764         * @og.rev 5.2.2.0 (2010/11/01) 新規追加
    765         * @og.rev 6.1.1.0 (2015/01/17) ｺﾒﾝﾄ修正｡separatorは､正規表現が使用できます｡
    766         *
    767         * @param   sepa 項目区切り文字(正規表現)
    768         * @see         #setMulti( String )
    769         */
    770        public void setSeparator( final String sepa ) {
    771                separator = nval( getRequestParameter( sepa ),separator );
    772        }
    773
    774        /**
    775         * 【TAG】数値型ｶﾗﾑに対して､ﾊｲﾌﾝで範囲指定をｶﾝﾏに分解するかどうか[true/false]を設定します(初期値:false)｡
    776         *
    777         * @og.tag
    778         * {&#064;XXXX} 変数に､"1,3,4-8" のような指定を行うと､"1,3,4,5,6,7,8" に変換します｡
    779         * これは､数値型ｶﾗﾑの範囲指定を､ﾊｲﾌﾝで行うことが出来る機能です｡
    780         * ﾊｲﾌﾝ以外は､ｶﾝﾏで区切って､普通の数値として指定できます｡
    781         * where 条件で言うと､ "where GOKI in ( {&#064;GOKI} )" という文字列に対して､
    782         * "where GOKI in ( 1,3,4,5,6,7,8 )" を作成することになります｡
    783         * 初期値は､ false (範囲変換しない) です｡
    784         * これは､数値ｶﾗﾑの範囲指定で､対象は自然数なので､小数や､ﾏｲﾅｽ､増加ｽﾃｯﾌﾟが１以外､
    785         * ﾏｲﾅｽｽﾃｯﾌﾟは扱えません｡
    786         * ちなみに､指定を数値ﾀｲﾌﾟのｶﾗﾑを使用すると､ｶﾝﾏを､自動削除してしまいますので､文字ｶﾗﾑを
    787         * ﾘｸｴｽﾄ変数に使用してください｡
    788         *
    789         * @og.rev 6.5.0.0 (2016/09/30) 数値型ｶﾗﾑの範囲指定(range)の追加｡
    790         *
    791         * @param   flag 範囲変換 [true:する/それ以外:しない]
    792         */
    793        public void setRange( final String flag ) {
    794                range = nval( getRequestParameter( flag ),range );
    795        }
    796
    797        /**
    798         * 【TAG】ﾊﾞｲﾝﾄﾞ変数(ﾌﾟﾚｰｽﾎﾙﾀﾞｰ)のvalueの条件作成を判定します(JDBCParepared用)｡
    799         *
    800         * @og.tag
    801         * value="CLM=?" bindVal="{&#064;CLM}"と指定されていた場合､
    802         * {&#064;CLM}に値が存在する場合のみ､CLM=?が指定されます｡
    803         *
    804         * {&#064;XXXX}形式での指定が可能で､valueの ? に対応した値をｾｯﾄします｡
    805         *
    806         * @og.rev 6.9.9.0 (2018/08/20) 新規追加( 5.10.2.1 (2018/08/18) )
    807         * @og.rev 8.0.0.0 (2021/07/31) placeHolder属性 → bindVal 名称変更
    808         *
    809         * @param val 値
    810         */
    811//      public void setPlaceHolder( final String val) {
    812        public void setBindVal( final String val) {
    813                // ﾘｸｴｽﾄ変数対応はここでは行わない
    814//              placeHolder = val;
    815                bindVal = val;
    816        }
    817
    818        /**
    819         * 【TAG】ﾘｸｴｽﾄ情報の ｼﾝｸﾞﾙｸｫｰﾄ(') 存在ﾁｪｯｸを実施するかどうか[true/false]を設定します
    820         *              (初期値:USE_SQL_INJECTION_CHECK[={@og.value SystemData#USE_SQL_INJECTION_CHECK}])｡
    821         *
    822         * @og.tag
    823         * ＳＱＬｲﾝｼﾞｪｸｼｮﾝ対策の一つとして､暫定的ではありますが､SQLのﾊﾟﾗﾒｰﾀに
    824         * 渡す文字列にｼﾝｸﾞﾙｸｫｰﾄ(') を許さない設定にすれば､ある程度は防止できます｡
    825         * 数字ﾀｲﾌﾟの引数には､ or 5=5 などのｼﾝｸﾞﾙｸｫｰﾄを使用しないｺｰﾄﾞを埋めても､
    826         * 数字ﾁｪｯｸで検出可能です｡文字ﾀｲﾌﾟの場合は､必ず (')をはずして､
    827         * ' or 'A' like 'A のような形式になる為､(')ﾁｪｯｸだけでも有効です｡
    828         * (') が含まれていたｴﾗｰにする(true)／かﾉｰﾁｪｯｸか(false)を指定します｡
    829         * (初期値:ｼｽﾃﾑ定数のUSE_SQL_INJECTION_CHECK[={@og.value SystemData#USE_SQL_INJECTION_CHECK}])｡
    830         *
    831         * @og.rev 4.0.0.0 (2005/08/31) 新規追加
    832         *
    833         * @param   flag ｸｫｰﾄﾁｪｯｸ [true:する/それ以外:しない]
    834         * @see         org.opengion.hayabusa.common.SystemData#USE_SQL_INJECTION_CHECK
    835         */
    836        public void setQuotCheck( final String flag ) {
    837                quotCheck = nval( getRequestParameter( flag ),quotCheck );
    838        }
    839
    840        /**
    841         * 【TAG】ﾘｸｴｽﾄ情報の HTMLTag開始/終了文字(&gt;&lt;) 存在ﾁｪｯｸを実施するかどうか[true/false]を設定します
    842         *              (初期値:USE_XSS_CHECK[={@og.value SystemData#USE_XSS_CHECK}])｡
    843         *
    844         * @og.tag
    845         * ｸﾛｽｻｲﾄｽｸﾘﾌﾟﾃｨﾝｸﾞ(XSS)対策の一環としてless/greater than signについてのﾁｪｯｸを行います｡
    846         * (&gt;&lt;) が含まれていたｴﾗｰにする(true)／かﾉｰﾁｪｯｸか(false)を指定します｡
    847         * (初期値:ｼｽﾃﾑ定数のUSE_XSS_CHECK[={@og.value SystemData#USE_XSS_CHECK}])｡
    848         *
    849         * @og.rev 5.0.0.2 (2009/09/15) 新規追加
    850         *
    851         * @param       flag    XSSﾁｪｯｸ [true:する/false:しない]
    852         * @see         org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK
    853         */
    854        public void setXssCheck( final String flag ) {
    855                xssCheck = nval( getRequestParameter( flag ),xssCheck );
    856        }
    857
    858        /**
    859         * ﾀｸﾞの名称を､返します｡
    860         * 自分自身のｸﾗｽ名より､自動的に取り出せないため､このﾒｿｯﾄﾞをｵｰﾊﾞｰﾗｲﾄﾞします｡
    861         *
    862         * @og.rev 4.0.0.0 (2005/01/31) 新規追加
    863         *
    864         * @return  ﾀｸﾞの名称
    865         * @og.rtnNotNull
    866         */
    867        @Override
    868        protected String getTagName() {
    869                return "and" ;
    870        }
    871
    872        /**
    873         * このｵﾌﾞｼﾞｪｸﾄの文字列表現を返します｡
    874         * 基本的にﾃﾞﾊﾞｯｸﾞ目的に使用します｡
    875         *
    876         * @return このｸﾗｽの文字列表現
    877         * @og.rtnNotNull
    878         */
    879        @Override
    880        public String toString() {
    881                return ToString.title( this.getClass().getName() )
    882                                .println( "VERSION"                     ,VERSION        )
    883                                .println( "startKey"            ,startKey       )
    884                                .println( "value"                       ,value          )
    885                                .println( "instrVals"           ,instrVals      )
    886                                .println( "multi"                       ,multi          )
    887                                .println( "quotCheck"           ,quotCheck      )
    888                                .println( "Other..."    ,getAttributes().getAttribute() )
    889                                .fixForm().toString() ;
    890        }
    891}