    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.HybsSystemException;
    019import org.opengion.fukurou.util.StringUtil;
    020import org.opengion.fukurou.util.Attributes;
    021import org.opengion.fukurou.util.ToString;                                              // 6.1.1.0 (2015/01/17)
    022
    023import static org.opengion.fukurou.util.StringUtil.nval ;
    024
    025/**
    026 * 検索結果のカラム表示に対して様々な属性を付加(マーキング)するタグです(参照:viewMarker)。
    027 *
    028 * このタグは、カラム毎にマーキングするタグです。親タグとして、viewMarker を
    029 * 使用する必要があります。
    030 * このタグでは、BODY部に指定した値を、レンデラーとして使用します。通常の文字は、
    031 * そのままで、{&#064;XXXX}で指定した変数は、リクエスト値を設定します。
    032 * [XXXX]で指定した値は、検索結果のDBTableModelの値を行毎に割り当てます。
    033 * マーカー指定の有無(マーカーするかしないか)は、onMark属性と、markList属性で
    034 * 指定します。markList属性に指定の値に、onMark属性に設定した値が存在する場合、
    035 * マーカーされます。 このmarkList属性には、"1" と "true"が初期設定
    036 * されているため、onMark属性に"1" または "true"を指定すれば、全行マークされます。
    037 * また、どちらの属性も、{&#064;XXXX} や、[XXXX]変数が使用できます。[XXXX]変数では、
    038 * 行毎に、onMark属性や、markList属性を設定できる為、(通常はどちらか固定)
    039 * 行毎の マーカー指定の有無を指定できます。
    040 * [XXXX]変数でカラム名の先頭に$を付加した場合(例:[$XXXX])は、元の値がURLエンコード
    041 * されて返されます。ただし、useFormatDeco="true" を指定すると、[$XXXX] は、
    042 * レンデラー処理された文字列を返します。
    043 * ※ <b>現段階では、viewMarker がカラム名をキーにcolumnMarkerオブジェクトを
    044 * 管理している為、行毎にマークの有無は指定できますが、マークを切り替える
    045 * 使い方が出来ません。</b>
    046 *
    047 *    6.7.6.0 (2017/03/17) [strictCheck属性]は、カラムＩＤの存在チェックを行うかどうかを指定します(初期値:true)
    048 *      true    カラムＩＤがDBTableModel に存在しない場合は、エラーになる。
    049 *      false   カラムＩＤがDBTableModel に存在しない場合は、無視する。
    050 *
    051 * @og.formSample
    052 * ●形式：&lt;og:columnMarker column="･･･" ･･･ &gt; ･･･ &lt;/og:columnMarker &gt;
    053 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
    054 *
    055 * ●Tag定義：
    056 *   &lt;og:columnMarker
    057 *       column             【TAG】マーク処理を行うカラム名を指定します
    058 *       columns            【TAG】マーク処理を行うカラム名をCSV形式(CSV形式)で複数指定します
    059 *       onMark             【TAG】マークを処理する(true or 1)/処理しない(false or 0)の設定を指定します(初期値:true)
    060 *       markList           【TAG】処理するマークを含むような文字列を、"|"区切りの文字列で指定します(初期値:"true|TRUE|1")
    061 *       instrVals          【TAG】スペースで区切られた複数の値について、マークします
    062 *       useFormatDeco      【TAG】[$XXXX],[#XXXX]機能を有効にします(初期値:false)
    063 *       strictCheck        【TAG】(通常は使いません)カラムＩＤの存在チェックを行うかどうか[true/false]を指定します(初期値:true)
    064 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
    065 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
    066 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない)
    067 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない)
    068 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
    069 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
    070 *   &gt;   ... Body ...
    071 *   &lt;/og:columnMarker&gt;
    072 *
    073 * ●使用例
    074 *     商品CD２(CDSYHN02)は赤字で表示する。
    075 *     商品CD３(CDSYHN03)は-----と表示する。
    076 *     &lt;og:viewMarker command="{&#064;command}"&gt;
    077 *         &lt;og:columnMarker column="CDSYHN02" onMark="true" &gt;
    078 *             &lt;font color='red'&gt;[VCDSYHN02]&lt;/font&gt;
    079 *         &lt;/og:columnMarker&gt;
    080 *         &lt;og:columnMarker column="CDSYHN03" onMark="[XXXX]" markList="[YYYY]" &gt;
    081 *             &lt;CENTER&gt;&lt;-----&lt;/CENTER&gt;
    082 *         &lt;/og:columnMarker&gt;
    083 *     &lt;/og:viewMarker&gt;
    084 *
    085 * @og.group 画面表示
    086 *
    087 * @version  4.0
    088 * @author       Kazuhiko Hasegawa
    089 * @since    JDK5.0,
    090 */
    091public class ColumnMarkerTag extends CommonTagSupport {
    092        /** このプログラムのVERSION文字列を設定します。   {@value} */
    093        private static final String VERSION = "6.7.6.0 (2017/03/17)" ;
    094        private static final long serialVersionUID = 676020170317L ;
    095
    096        private String          column          ;
    097        private String[]        columns         ;
    098        private String          onMark          = "true";                       // true または 1
    099        // 3.5.2.0 (2003/10/20)
    100        private String          markList        = "true|TRUE|1";        // true または 1
    101        private String          instrVals       ;                                       // 3.8.8.1 (2007/01/06)
    102
    103        private String          useFormatDeco   = "false";              // 5.6.3.0 (2013/04/01) [$XXXX],[#XXXX]機能を有効にするかどうか
    104        private boolean         strictCheck             = true;                 // 6.7.6.0 (2017/03/17) カラムＩＤの存在チェックを行うかどうかを指定します。
    105
    106        /**
    107         * デフォルトコンストラクター
    108         *
    109         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
    110         */
    111        public ColumnMarkerTag() { super(); }           // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    112
    113        /**
    114         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
    115         *
    116         * @og.rev 6.3.4.0 (2015/08/01) caseKey,caseVal,caseNN,caseNull,caseIf 属性対応
    117         *
    118         * @return      後続処理の指示( EVAL_BODY_BUFFERED )
    119         */
    120        @Override
    121        public int doStartTag() {
    122                // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
    123                // 反転注意
    124                return useTag()
    125                                        ? EVAL_BODY_BUFFERED    // Body を評価する。( extends BodyTagSupport 時)
    126                                        : SKIP_BODY ;
    127
    128        }
    129
    130        /**
    131         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
    132         *
    133         * @og.rev 3.1.1.0 (2003/03/28) ボディの内容を取得する処理を、CommonTagSupport で行う。
    134         * @og.rev 3.5.2.0 (2003/10/20) markList属性を追加
    135         * @og.rev 3.8.8.1 (2007/01/06) instrVals属性を追加
    136         * @og.rev 4.0.0.0 (2005/08/31) 同一カラムの複数登録を許可します。
    137         * @og.rev 5.6.3.0 (2013/04/01) useFormatDeco属性を追加（[$XXXX],[#XXXX]機能を有効にするかどうか）
    138         * @og.rev 6.7.6.0 (2017/03/17) strictCheck 追加。
    139         *
    140         * @return      後続処理の指示(SKIP_BODY)
    141         */
    142        @Override
    143        public int doAfterBody() {
    144                final ViewMarkerTag viewMarker = (ViewMarkerTag)findAncestorWithClass( this,ViewMarkerTag.class );
    145                if( viewMarker != null ) {
    146                        final String marker = getBodyString();
    147
    148                        set( "body"             ,marker );
    149                        set( "onMark"   ,onMark );
    150                        set( "markList" ,markList );
    151                        set( "instrVals",instrVals );                   // 3.8.8.1 (2007/01/06)
    152                        set( "useFormatDeco", useFormatDeco );  // 5.6.3.0 (2013/04/01) [$XXXX],[#XXXX]機能を有効にするかどうか
    153                        set( "strictCheck"  , String.valueOf( strictCheck ) );          // 6.7.6.0 (2017/03/17)
    154
    155                        boolean flag = false;
    156                        if( column != null && column.length() > 0 ) {
    157                                // 4.0.0 (2005/08/31) 同一カラムの複数登録を許可します。
    158                                set( "column",column );
    159                                viewMarker.addAttribute( getAttributes() );
    160                                flag = true;
    161                        }
    162
    163                        if( columns != null && columns.length > 0 ) {
    164                                flag = true;
    165                                for( int i=0; i<columns.length; i++ ) {
    166                                        final String newMarker = StringUtil.replace( marker,"[$1]","[" + columns[i] + "]" );
    167                                        set( "body"  ,newMarker );
    168                                        // 4.0.0 (2005/08/31) 同一カラムの複数登録を許可します。
    169                                        set( "column",columns[i] );
    170                                        viewMarker.addAttribute( new Attributes( getAttributes() ) );
    171                                }
    172                        }
    173
    174                        if( ! flag ) {
    175                                final String errMsg = "colum か、columns は、どちらか必ず必要です。";
    176                                throw new HybsSystemException( errMsg );
    177                        }
    178                }
    179                return SKIP_BODY ;
    180        }
    181
    182        /**
    183         * タグリブオブジェクトをリリースします。
    184         *
    185         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
    186         *
    187         * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
    188         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
    189         * @og.rev 3.5.2.0 (2003/10/20) markList属性を追加
    190         * @og.rev 3.8.8.1 (2007/01/06) instrVals属性を追加
    191         * @og.rev 5.6.3.0 (2013/04/01) useFormatDeco属性を追加
    192         * @og.rev 6.7.6.0 (2017/03/17) strictCheck 追加。
    193         *
    194         */
    195        @Override
    196        protected void release2() {
    197                super.release2();
    198                column          = null;
    199                columns         = null;
    200                onMark          = "true";                       // true または 1
    201                markList        = "true|TRUE|1";
    202                instrVals       = null;                         // 3.8.8.1 (2007/01/06)
    203                useFormatDeco   = "false";              // 5.6.3.0 (2013/04/01) [$XXXX],[#XXXX]機能を有効にするかどうか
    204                strictCheck             = true;                 // 6.7.6.0 (2017/03/17)
    205        }
    206
    207        /**
    208         * 【TAG】マーク処理を行うカラム名を指定します。
    209         *
    210         * @og.tag
    211         * このカラム名のTableModelに対して、マークを処理します。
    212         *
    213         * @param       clm カラム名
    214         */
    215        public void setColumn( final String clm ) {
    216                column = getRequestParameter( clm );
    217        }
    218
    219        /**
    220         * 【TAG】マーク処理を行うカラム名をCSV形式(CSV形式)で複数指定します。
    221         *
    222         * @og.tag
    223         * この複数のカラム名のTableModelに対して、 マークを処理します。
    224         * カラム名は、CSV形式で複数指定することができます。その場合は、
    225         * 指定のカラムに対して、すべて同一の処理を行います。
    226         * 分解方法は、通常のパラメータ取得後に、CSV分解します。
    227         *
    228         * @og.rev 3.5.6.2 (2004/07/05) 先に配列に分解してからリクエスト変数の値を取得
    229         * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。
    230         *
    231         * @param       clms マーク処理を行うカラム名(CSV形式)
    232         */
    233        public void setColumns( final String clms ) {
    234                columns = StringUtil.csv2Array( getRequestParameter( clms ) );
    235                if( columns.length == 0 ) { columns = null; }
    236        }
    237
    238        /**
    239         * 【TAG】マークを処理する(true or 1)/処理しない(false or 0)の設定を指定します(初期値:true)。
    240         *
    241         * @og.tag
    242         * マークを処理する場合は、"true"(または "1")
    243         * 処理しない場合は, "true以外"(または "0")をセットします。
    244         * 初期値は、 "true"(マークを処理する)です。
    245         * さらに、[カラム名] で、動的にカラムの値で、マークをする、しないを
    246         * 選ぶ事が可能になります。値は、"true"(または "1") で、マークします。
    247         * 追記 3.5.2.0 (2003/10/20)：markList属性に、処理対象文字列郡を指定できます。
    248         * これにより、マークを処理するかどうかの判断が、true,1 以外にも使用できるようになりました。
    249         *
    250         * @og.rev 3.5.0.0 (2003/09/17) onMark に、[カラム名] の値をセットできるように修正。
    251         *
    252         * @param       flag マークの処理 [true,1:処理する/それ以外:処理しない]
    253         */
    254        public void setOnMark( final String flag ) {
    255                onMark = nval( getRequestParameter( flag ),onMark );
    256        }
    257
    258        /**
    259         * 【TAG】処理するマークを含むような文字列を、"|"区切りの文字列で指定します(初期値:"true|TRUE|1")。
    260         *
    261         * @og.tag
    262         * markListで与えられた文字列に、onMark文字列(大文字/小文字の区別あり)が
    263         * 含まれていれば、処理します。
    264         * 例えば、"A","B","C" という文字列が、onMark で指定された
    265         * 場合に処理するようにしたい場合は、"A|B|C" をセットします。
    266         * 内部的には、markList.indexOf( onMark ) ＞＝ 0 で判定しています。
    267         * markList には、[カラム名]指定が可能です。
    268         * 初期値は、 "true|TRUE|1"です。
    269         *
    270         * 6.7.2.0 (2017/01/16) 追加
    271         * markListの先頭に、"?" をつけると、正規表現によるマッチング判定を行います。
    272         * 内部的には、onMark.matches( markList.substring(1) ) で判定します。
    273         *
    274         * @og.rev 3.5.2.0 (2003/10/20) 新規追加
    275         * @og.rev 6.7.2.0 (2017/01/16) markListの先頭が、"?" の場合、正規表現で判定します。
    276         *
    277         * @param       list 処理するマーク (indexOf による含む/含まない判定)
    278         */
    279        public void setMarkList( final String list ) {
    280                markList = nval( getRequestParameter( list ),markList );
    281        }
    282
    283        /**
    284         * 【TAG】スペースで区切られた複数の値について、マークします。
    285         *
    286         * @og.tag
    287         * 最終的に作成された表示結果に対して、引数の文字列を含む箇所に、
    288         * <span class="instr0">引数文字列</span> 文字列と置き換えます。
    289         * 0 の部分は、引数文字列の現れた順番を指定します。
    290         * これにより、部分検索された箇所のみにマークすることが可能です。
    291         * 部分文字列は、スペースで区切り、それぞれ独立した形でマーク
    292         * されますので、検索エンジン等で検索したキャッシュ表示のような
    293         * 効果を持たすことが可能になります。
    294         *
    295         * @param       val スペースで区切られた複数の値
    296         * @see         SqlAndTag#setInstrVals( String )
    297         */
    298        public void setInstrVals( final String val ) {
    299                instrVals = nval( getRequestParameter( val ),instrVals );
    300        }
    301
    302        /**
    303         * 【TAG】[$XXXX],[#XXXX]機能を有効にするかどうか[true:有効/false:無効]指定します(初期値:false)。
    304         *
    305         * @og.tag
    306         * カラムのフォーマット処理で、[$XXXX],[#XXXX]などの修飾記号を付けると、
    307         * データでない値を出力できます。
    308         * [$XXXX] は、レンデラー処理された文字列を、[#XXXX]は、ラベルリソースを出力します。
    309         * この、columnMarker のデフォルトでは、[$XXXX]は、URLエンコード処理された結果が
    310         * 返されます。他の処理(viewタグのボディ部等)とは異なる処理ですが、互換性のため、
    311         * [$XXXX]のレンデラー処理は、行われません。
    312         * この属性で、"true" を設定すれば、他のフォーマット処理と同じ処理が実行されます。
    313         * 初期値は、互換性を考慮し、"false" になっています。
    314         *
    315         * @og.rev 5.6.3.0 (2013/04/01) 新規追加
    316         *
    317         * @param       val 機能設定 [true:有効/false:無効]
    318         */
    319        public void setUseFormatDeco( final String val ) {
    320                useFormatDeco = nval( getRequestParameter( val ),useFormatDeco );
    321        }
    322
    323        /**
    324         * 【TAG】(通常は使いません)カラムＩＤの存在チェックを行うかどうか[true/false]を指定します(初期値:true)。
    325         *
    326         * @og.tag
    327         * true の場合、カラムＩＤがDBTableModel に存在しない場合は、エラーになります。
    328         * false の場合、カラムＩＤがDBTableModel に存在しない場合は、無視します。
    329         * これは、検索条件によって、設定されるカラムが異なる場合でも、後続処理を
    330         * 正常に動作させたい場合に、使用します。
    331         * 初期値は true (チェックを行う) です。
    332         *
    333         * @og.rev 6.7.6.0 (2017/03/17) strictCheck 追加。
    334         *
    335         * @param  check 存在チェック [true:行う/false:行わない]
    336         */
    337        public void setStrictCheck( final String check ) {
    338                strictCheck = nval( getRequestParameter( check ),strictCheck );
    339        }
    340
    341        /**
    342         * このオブジェクトの文字列表現を返します。
    343         * 基本的にデバッグ目的に使用します。
    344         *
    345         * @return このクラスの文字列表現
    346         * @og.rtnNotNull
    347         */
    348        @Override
    349        public String toString() {
    350                return ToString.title( this.getClass().getName() )
    351                                .println( "VERSION"             ,VERSION        )
    352                                .println( "column"              ,column         )
    353                                .println( "columns"             ,columns        )
    354                                .println( "onMark"              ,onMark         )
    355                                .println( "markList"    ,markList       )
    356                                .println( "strictCheck" ,strictCheck    )               // 6.7.6.0 (2017/03/17)
    357                                .println( "Other..."    ,getAttributes().getAttribute() )
    358                                .fixForm().toString() ;
    359        }
    360}