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.hayabusa.resource.LabelInterface;
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
025/**
026 * 画面にラベルリソース等のメッセージを表示させるタグです。
027 *
028 * lbl 属性に ラベルリソース のキーを与えることで、 ロケールにあわせたリソースを使用して、
029 * 画面に表示します。
030 * 違う値をセットした場合は、 セットした値が、そのまま出力されます。これは、ロケールが
031 * 見つからなかった場合の標準の対応方法です。
032 * ロケールは、ユーザー情報の lang 属性を初期値で使用し、 セットされていない場合は、
033 * リクエスト情報のロケールから取得します。
034 * lbl 属性を使用する場合、val0 ~ val9 までの引数を使用することができます。これは、
035 * メッセージフォーマットの、引数 {0} ~ {9} に対応して割り付けられます。
036 *
037 * @og.formSample
038 * ●形式:<og:message lbl="…" val0=[…] … />
039 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します)
040 *
041 * ●Tag定義:
042 *   <og:message
043 *       lbl                【TAG】ラベルリソースのラベルIDを指定します
044 *       language           【TAG】タグ内部で使用する言語コード[ja/en/zh/…]を指定します
045 *       command            【TAG】コマンド (INSERT,COPY,MODIFY,DELETE)をセットします
046 *       comment            【TAG】コメントを指定します
047 *       type               【TAG】タイプを(Label,Short,Tips,Description)から指定します(初期値:Label)
048 *       val0               【TAG】メッセージの引数{0}を指定します
049 *       val1               【TAG】メッセージの引数{1}を指定します
050 *       val2               【TAG】メッセージの引数{2}を指定します
051 *       val3               【TAG】メッセージの引数{3}を指定します
052 *       val4               【TAG】メッセージの引数{4}を指定します
053 *       val5               【TAG】メッセージの引数{5}を指定します
054 *       val6               【TAG】メッセージの引数{6}を指定します
055 *       val7               【TAG】メッセージの引数{7}を指定します
056 *       val8               【TAG】メッセージの引数{8}を指定します
057 *       val9               【TAG】メッセージの引数{9}を指定します
058 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
059 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
060 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない)
061 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない)
062 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
063 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
064 *   >   ... Body ...
065 *   </og:message>
066 *
067 * ●使用例
068 *     <og:message lbl="MSG0032" language="ja" />
069 *
070 *        lbl       : MessageResource.properties のキー
071 *        language  : ロケール(オプション)
072 *
073 *     例1)
074 *         <og:message lbl="MSG0032" >検索条件</og:message>
075 *
076 *        BODY 部分は、無視されます。コメント等に使用できます。
077 *        HTMLファイルには、コメント部分は出力されません。
078 *
079 *        typeをTipsにした場合には出力をclass=ogmsgのspanタグで囲います。   5.9.22.2 (2017/07/21)
080 *
081 * @og.group 画面部品
082 *
083 * @version  4.0
084 * @author   Kazuhiko Hasegawa
085 * @since    JDK5.0,
086 */
087public class MessageTag extends CommonTagSupport {
088        /** このプログラムのVERSION文字列を設定します。   {@value} */
089        private static final String VERSION = "6.8.5.0 (2018/01/09)" ;
090        private static final long serialVersionUID = 685020180109L ;
091
092        private String          comment ;
093        private String[]        values  ;
094        // 4.0.0 (2005/01/31) メッセージの種類を指定できるようにします。
095        private String          type    = "Label" ;     // Label,Short,Tips,Description が指定できます。
096        private String          cmdMsg  ;
097
098        private static final String[] TYPE_LIST = { "Label","Short","Tips","Description" };
099
100        // 6.8.5.0 (2018/01/09) PMD Variables that are final and static should be all capitals。tipsPre,tipsSuf → TIPS_PRE,TIPS_SUF
101        private static final String TIPS_PRE = "<span class=\"ogmsg\">"; // 5.9.22.2 (2017/07/21)
102        private static final String TIPS_SUF = "</span>";
103
104        /**
105         * デフォルトコンストラクター
106         *
107         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
108         */
109        public MessageTag() { super(); }                // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
110
111        /**
112         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
113         *
114         * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
115         *
116         * @return      後続処理の指示( EVAL_BODY_BUFFERED )
117         */
118        @Override
119        public int doStartTag() {
120                // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
121                // 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
122                return useTag()
123                                        ? EVAL_BODY_BUFFERED            // Body を評価する。( extends BodyTagSupport 時)
124                                        : SKIP_BODY ;                           // Body を評価しない
125
126        }
127
128        /**
129         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
130         *
131         * @og.rev 3.1.1.0 (2003/03/28) ボディの内容を取得する処理を、CommonTagSupport で行う。
132         *
133         * @return      後続処理の指示(SKIP_BODY)
134         */
135        @Override
136        public int doAfterBody() {
137                final String str = getBodyString();
138
139                if( str != null && str.length() > 0 ) {
140                        comment = StringUtil.htmlFilter( str );
141                }
142
143                return SKIP_BODY ;
144        }
145
146        /**
147         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
148         *
149         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
150         * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
151         *
152         * @return      後続処理の指示
153         */
154        @Override
155        public int doEndTag() {
156                debugPrint();           // 4.0.0 (2005/02/28)
157                // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
158                if( useTag() ) {
159                        jspPrint( makeTag() );
160                }
161                return EVAL_PAGE ;
162        }
163
164        /**
165         * タグリブオブジェクトをリリースします。
166         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
167         *
168         * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
169         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
170         *
171         */
172        @Override
173        protected void release2() {
174                super.release2();
175                comment = null;
176                values  = null;
177                type    = "Label" ;     // Label,Short,Tips,Description が指定できます。
178                cmdMsg  = null;
179        }
180
181        /**
182         * 表示用の文字列を指定します。
183         *
184         * @og.rev 4.0.0.0 (2005/01/31) タイプ別メッセージ情報を返します。
185         * @og.rev 4.0.0.0 (2007/10/18) メッセージリソース統合( getResource().getMessage ⇒ getResource().getLabel )
186         * @og.ref 5.9.22.2 (2017/07/21) Tipsの場合のみ、前後をclass=ogmsg付きのspanで囲います。
187         * @og.rev 6.8.5.0 (2018/01/09) PMD Variables that are final and static should be all capitals。tipsPre,tipsSuf → TIPS_PRE,TIPS_SUF
188         *
189         * @return  変換後の文字列
190         */
191        private String makeTag() {
192                String val  = null;
193
194                final LabelInterface label = getLabelInterface();
195
196                final char ch = type.charAt(0); // Label,Short,Tips,Description
197                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
198                if( label == null ) {
199                        val = cmdMsg == null ? comment : getResource().getLabel( cmdMsg );      // cmdMsg = INSERT,COPY,MODIFY,DELETE,null
200                }
201                else {
202                        switch( ch ) {
203                                case 'L': val = label.getMessage( values );     break;
204                                case 'S': val = label.getShortLabel();          break;
205                                case 'T': val = TIPS_PRE + label.getLongLabel() + TIPS_SUF; break;      // 6.8.5.0 (2018/01/09)
206                                case 'D': val = label.getDescription();         break;
207                                default :                                                                       break;
208                        }
209                }
210
211                return val;
212        }
213
214        /**
215         * 【TAG】コメントを指定します。
216         *
217         * @og.tag
218         * msg 属性でメッセージリソースから読み取りますが,開発途中で
219         * リソース登録を済ましていない状態でコメントを入れる場合に、
220         * 直接コメントをかけるようにします。
221         *
222         * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更
223         * @og.rev 3.0.0.0 (2002/12/25) StringUtil#changeString 廃止
224         *
225         * @param   cmnt コメント文字列
226         */
227        public void setComment( final String cmnt ) {
228                comment = cmnt;
229        }
230
231        /**
232         * 【TAG】タイプ[Label/Short/Tips/Description]を指定します(初期値:Label)。
233         *
234         * @og.tag
235         * タイプは、ラベル/メッセージリソースのどの情報を取得したいかを指定できます。
236         * 従来のラベル/メッセージは、Label に相当します。
237         * なお、指定は、それぞれの頭文字('L','S','T','D')のみでも可能です。
238         * 初期値は、"Label" です。
239         * ・Label  : ラベル/メッセージ表示
240         * ・Short  : 表形式で使用する短いラベル表示
241         * ・Tips   : ラベルの上にTips表示
242         * ・Description : 概要説明を表示
243         *
244         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
245         *
246         * @param   tp タイプ文字列 [Label/Short/Tips/Description]
247         */
248        public void setType( final String tp ) {
249                type = nval( getRequestParameter( tp ),type );
250
251                final char ch = type.charAt(0); // Label,Short,Tips,Description
252
253                if( "LSTD".indexOf( ch ) < 0 ) {
254                        final String errMsg = "type に、指定不可能な文字が設定されました。type=[" + type
255                                        + "] TYPE_LIST=[" + StringUtil.array2csv( TYPE_LIST ) + "]";
256                        throw new HybsSystemException( errMsg );
257                }
258        }
259
260        /**
261         * 【TAG】メッセージの引数{0}を指定します。
262         *
263         * @og.tag メッセージの引数を指定します。
264         *
265         * @param   value メッセージの引数
266         */
267        public void setVal0( final String value ) { setValues( 0, value ); }
268
269        /**
270         * 【TAG】メッセージの引数{1}を指定します。
271         *
272         * @og.tag メッセージの引数を指定します。
273         *
274         * @param   value メッセージの引数
275         */
276        public void setVal1( final String value ) { setValues( 1, value ); }
277
278        /**
279         * 【TAG】メッセージの引数{2}を指定します。
280         *
281         * @og.tag メッセージの引数を指定します。
282         *
283         * @param   value メッセージの引数
284         */
285        public void setVal2( final String value ) { setValues( 2, value ); }
286
287        /**
288         * 【TAG】メッセージの引数{3}を指定します。
289         *
290         * @og.tag メッセージの引数を指定します。
291         *
292         * @param   value メッセージの引数
293         */
294        public void setVal3( final String value ) { setValues( 3, value ); }
295
296        /**
297         * 【TAG】メッセージの引数{4}を指定します。
298         *
299         * @og.tag メッセージの引数を指定します。
300         *
301         * @param   value メッセージの引数
302         */
303        public void setVal4( final String value ) { setValues( 4, value ); }
304
305        /**
306         * 【TAG】メッセージの引数{5}を指定します。
307         *
308         * @og.tag メッセージの引数を指定します。
309         *
310         * @param   value メッセージの引数
311         */
312        public void setVal5( final String value ) { setValues( 5, value ); }
313
314        /**
315         * 【TAG】メッセージの引数{6}を指定します。
316         *
317         * @og.tag メッセージの引数を指定します。
318         *
319         * @param   value メッセージの引数
320         */
321        public void setVal6( final String value ) { setValues( 6, value ); }
322
323        /**
324         * 【TAG】メッセージの引数{7}を指定します。
325         *
326         * @og.tag メッセージの引数を指定します。
327         *
328         * @param   value メッセージの引数
329         */
330        public void setVal7( final String value ) { setValues( 7, value ); }
331
332        /**
333         * 【TAG】メッセージの引数{8}を指定します。
334         *
335         * @og.tag メッセージの引数を指定します。
336         *
337         * @param   value メッセージの引数
338         */
339        public void setVal8( final String value ) { setValues( 8, value ); }
340
341        /**
342         * 【TAG】メッセージの引数{9}を指定します。
343         *
344         * @og.tag メッセージの引数{9}を指定します。
345         *
346         * @param   value メッセージの引数
347         */
348        public void setVal9( final String value ) { setValues( 9, value ); }
349
350        /**
351         * メッセージの引数を指定します。
352         *
353         * @param   no    メッセージの引数の配列番号
354         * @param   value メッセージの引数
355         */
356        private void setValues( final int no,final String val ) {
357                if( values == null ) { values = new String[10]; }
358                values[no] = getRequestParameter( val );
359        }
360
361        /**
362         * 【TAG】コマンド (INSERT,COPY,MODIFY,DELETE)をセットします。
363         *
364         * @og.tag
365         * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
366         * フィールド定数値のいづれかを、指定できます。
367         * コマンド (INSERT,COPY,MODIFY,DELETE)に対応したメッセージを表示します。
368         * INSERT : MSG0044  追加処理を行います。
369         * COPY   : MSG0045  複写処理を行います。
370         * MODIFY : MSG0046  変更処理を行います。
371         * DELETE : MSG0047  削除処理を行います。
372         *
373         * なお、command によるメッセージの自動選択は、lbl ともにセットされていない
374         * 場合にのみ有効になります。
375         *
376         * @og.rev 4.0.0.0 (2006/11/31) 新規登録
377         *
378         * @param       cmd コマンド (public static final 宣言されている文字列)
379         */
380        public void setCommand( final String cmd ) {
381                final String cmd2 = nval( getRequestParameter( cmd ),null );
382                if(      "INSERT".equalsIgnoreCase( cmd2 ) ) { cmdMsg = "MSG0044"; }
383                else if( "COPY".equalsIgnoreCase(   cmd2 ) ) { cmdMsg = "MSG0045"; }
384                else if( "MODIFY".equalsIgnoreCase( cmd2 ) ) { cmdMsg = "MSG0046"; }
385                else if( "DELETE".equalsIgnoreCase( cmd2 ) ) { cmdMsg = "MSG0047"; }
386                else { cmdMsg = null; }
387        }
388
389        /**
390         * このオブジェクトの文字列表現を返します。
391         * 基本的にデバッグ目的に使用します。
392         *
393         * @return このクラスの文字列表現
394         * @og.rtnNotNull
395         */
396        @Override
397        public String toString() {
398                return ToString.title( this.getClass().getName() )
399                                .println( "VERSION"             ,VERSION        )
400                                .println( "comment"             ,comment        )
401                                .println( "values"              ,values         )
402                                .println( "type"                ,type           )
403                                .println( "TYPE_LIST"   ,TYPE_LIST      )
404                                .println( "Other..."    ,getAttributes().getAttribute() )
405                                .fixForm().toString() ;
406        }
407}