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 = "7.1.0.1 (2020/02/07)" ;
090        private static final long serialVersionUID = 710120200207L ;
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         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
129         *
130         * @og.rev 3.1.1.0 (2003/03/28) ボディの内容を取得する処理を、CommonTagSupport で行う。
131         *
132         * @return      後続処理の指示(SKIP_BODY)
133         */
134        @Override
135        public int doAfterBody() {
136                final String str = getBodyString();
137
138                if( str != null && str.length() > 0 ) {
139                        comment = StringUtil.htmlFilter( str );
140                }
141
142                return SKIP_BODY ;
143        }
144
145        /**
146         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
147         *
148         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
149         * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
150         *
151         * @return      後続処理の指示
152         */
153        @Override
154        public int doEndTag() {
155                debugPrint();           // 4.0.0 (2005/02/28)
156                // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
157                if( useTag() ) {
158                        jspPrint( makeTag() );
159                }
160                return EVAL_PAGE ;
161        }
162
163        /**
164         * タグリブオブジェクトをリリースします。
165         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
166         *
167         * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
168         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
169         *
170         */
171        @Override
172        protected void release2() {
173                super.release2();
174                comment = null;
175                values  = null;
176                type    = "Label" ;     // Label,Short,Tips,Description が指定できます。
177                cmdMsg  = null;
178        }
179
180        /**
181         * 表示用の文字列を指定します。
182         *
183         * @og.rev 4.0.0.0 (2005/01/31) タイプ別メッセージ情報を返します。
184         * @og.rev 4.0.0.0 (2007/10/18) メッセージリソース統合( getResource().getMessage ⇒ getResource().getLabel )
185         * @og.ref 5.9.22.2 (2017/07/21) Tipsの場合のみ、前後をclass=ogmsg付きのspanで囲います。
186         * @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
187         * @og.rev 7.1.0.1 (2020/02/07) ショートラベルと概要に引数を渡します。
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 'S': val = label.getShortMessage( values );        break;                  // 7.1.0.1 (2020/02/07)
206                                case 'T': val = TIPS_PRE + label.getLongLabel() + TIPS_SUF; break;      // 6.8.5.0 (2018/01/09)
207//                              case 'D': val = label.getDescription();         break;
208                                case 'D': val = label.getDescription( values);          break;                  // 7.1.0.1 (2020/02/07)
209                                default :                                                                                       break;
210                        }
211                }
212
213                return val;
214        }
215
216        /**
217         * 【TAG】コメントを指定します。
218         *
219         * @og.tag
220         * msg 属性でメッセージリソースから読み取りますが、開発途中で
221         * リソース登録を済ましていない状態でコメントを入れる場合に、
222         * 直接コメントをかけるようにします。
223         *
224         * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更
225         * @og.rev 3.0.0.0 (2002/12/25) StringUtil#changeString 廃止
226         *
227         * @param   cmnt コメント文字列
228         */
229        public void setComment( final String cmnt ) {
230                comment = cmnt;
231        }
232
233        /**
234         * 【TAG】タイプ[Label/Short/Tips/Description]を指定します(初期値:Label)。
235         *
236         * @og.tag
237         * タイプは、ラベル/メッセージリソースのどの情報を取得したいかを指定できます。
238         * 従来のラベル/メッセージは、Label に相当します。
239         * なお、指定は、それぞれの頭文字('L','S','T','D')のみでも可能です。
240         * 初期値は、"Label" です。
241         * ・Label  : ラベル/メッセージ表示
242         * ・Short  : 表形式で使用する短いラベル表示
243         * ・Tips   : ラベルの上にTips表示
244         * ・Description : 概要説明を表示
245         *
246         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
247         *
248         * @param   tp タイプ文字列 [Label/Short/Tips/Description]
249         */
250        public void setType( final String tp ) {
251                type = nval( getRequestParameter( tp ),type );
252
253                final char ch = type.charAt(0); // Label,Short,Tips,Description
254
255                if( "LSTD".indexOf( ch ) < 0 ) {
256                        final String errMsg = "type に、指定不可能な文字が設定されました。type=[" + type
257                                        + "] TYPE_LIST=[" + StringUtil.array2csv( TYPE_LIST ) + "]";
258                        throw new HybsSystemException( errMsg );
259                }
260        }
261
262        /**
263         * 【TAG】メッセージの引数{0}を指定します。
264         *
265         * @og.tag メッセージの引数を指定します。
266         *
267         * @param   value メッセージの引数
268         */
269        public void setVal0( final String value ) { setValues( 0, value ); }
270
271        /**
272         * 【TAG】メッセージの引数{1}を指定します。
273         *
274         * @og.tag メッセージの引数を指定します。
275         *
276         * @param   value メッセージの引数
277         */
278        public void setVal1( final String value ) { setValues( 1, value ); }
279
280        /**
281         * 【TAG】メッセージの引数{2}を指定します。
282         *
283         * @og.tag メッセージの引数を指定します。
284         *
285         * @param   value メッセージの引数
286         */
287        public void setVal2( final String value ) { setValues( 2, value ); }
288
289        /**
290         * 【TAG】メッセージの引数{3}を指定します。
291         *
292         * @og.tag メッセージの引数を指定します。
293         *
294         * @param   value メッセージの引数
295         */
296        public void setVal3( final String value ) { setValues( 3, value ); }
297
298        /**
299         * 【TAG】メッセージの引数{4}を指定します。
300         *
301         * @og.tag メッセージの引数を指定します。
302         *
303         * @param   value メッセージの引数
304         */
305        public void setVal4( final String value ) { setValues( 4, value ); }
306
307        /**
308         * 【TAG】メッセージの引数{5}を指定します。
309         *
310         * @og.tag メッセージの引数を指定します。
311         *
312         * @param   value メッセージの引数
313         */
314        public void setVal5( final String value ) { setValues( 5, value ); }
315
316        /**
317         * 【TAG】メッセージの引数{6}を指定します。
318         *
319         * @og.tag メッセージの引数を指定します。
320         *
321         * @param   value メッセージの引数
322         */
323        public void setVal6( final String value ) { setValues( 6, value ); }
324
325        /**
326         * 【TAG】メッセージの引数{7}を指定します。
327         *
328         * @og.tag メッセージの引数を指定します。
329         *
330         * @param   value メッセージの引数
331         */
332        public void setVal7( final String value ) { setValues( 7, value ); }
333
334        /**
335         * 【TAG】メッセージの引数{8}を指定します。
336         *
337         * @og.tag メッセージの引数を指定します。
338         *
339         * @param   value メッセージの引数
340         */
341        public void setVal8( final String value ) { setValues( 8, value ); }
342
343        /**
344         * 【TAG】メッセージの引数{9}を指定します。
345         *
346         * @og.tag メッセージの引数{9}を指定します。
347         *
348         * @param   value メッセージの引数
349         */
350        public void setVal9( final String value ) { setValues( 9, value ); }
351
352        /**
353         * メッセージの引数を指定します。
354         *
355         * @param   no    メッセージの引数の配列番号
356         * @param   value メッセージの引数
357         */
358        private void setValues( final int no,final String val ) {
359                if( values == null ) { values = new String[10]; }
360                values[no] = getRequestParameter( val );
361        }
362
363        /**
364         * 【TAG】コマンド (INSERT,COPY,MODIFY,DELETE)をセットします。
365         *
366         * @og.tag
367         * コマンドは、HTMLから(get/post)指定されますので、CMD_xxx で設定される
368         * フィールド定数値のいづれかを、指定できます。
369         * コマンド (INSERT,COPY,MODIFY,DELETE)に対応したメッセージを表示します。
370         * INSERT : MSG0044  追加処理を行います。
371         * COPY   : MSG0045  複写処理を行います。
372         * MODIFY : MSG0046  変更処理を行います。
373         * DELETE : MSG0047  削除処理を行います。
374         *
375         * なお、command によるメッセージの自動選択は、lbl ともにセットされていない
376         * 場合にのみ有効になります。
377         *
378         * @og.rev 4.0.0.0 (2006/11/31) 新規登録
379         *
380         * @param       cmd コマンド (public static final 宣言されている文字列)
381         */
382        public void setCommand( final String cmd ) {
383                final String cmd2 = nval( getRequestParameter( cmd ),null );
384                if(      "INSERT".equalsIgnoreCase( cmd2 ) ) { cmdMsg = "MSG0044"; }
385                else if( "COPY".equalsIgnoreCase(   cmd2 ) ) { cmdMsg = "MSG0045"; }
386                else if( "MODIFY".equalsIgnoreCase( cmd2 ) ) { cmdMsg = "MSG0046"; }
387                else if( "DELETE".equalsIgnoreCase( cmd2 ) ) { cmdMsg = "MSG0047"; }
388                else { cmdMsg = null; }
389        }
390
391        /**
392         * このオブジェクトの文字列表現を返します。
393         * 基本的にデバッグ目的に使用します。
394         *
395         * @return このクラスの文字列表現
396         * @og.rtnNotNull
397         */
398        @Override
399        public String toString() {
400                return ToString.title( this.getClass().getName() )
401                                .println( "VERSION"             ,VERSION        )
402                                .println( "comment"             ,comment        )
403                                .println( "values"              ,values         )
404                                .println( "type"                ,type           )
405                                .println( "TYPE_LIST"   ,TYPE_LIST      )
406                                .println( "Other..."    ,getAttributes().getAttribute() )
407                                .fixForm().toString() ;
408        }
409}