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.db;
017
018import org.opengion.fukurou.system.LogWriter;
019import org.opengion.hayabusa.resource.CodeData;
020import org.opengion.fukurou.util.StringUtil ;                                           // 6.2.2.0 (2015/03/27)
021
022import static org.opengion.fukurou.system.HybsConst.CR ;                        // 6.1.0.0 (2014/12/26)
023import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.1.0.0 (2014/12/26) refactoring
024
025/**
026 * データのコード情報を取り扱うクラスです。
027 *
028 * コードのキーとラベルの情報から、HTMLのメニューやリストを作成するための オプション
029 * タグを作成したり、与えられたキーをもとに、チェック済みのオプションタグを作成したり
030 * します。
031 *
032 * @og.rev 5.7.7.1 (2014/06/13) Selection_NULL を 基本実装とします。
033 * @og.group 選択データ制御
034 *
035 * @version  4.0
036 * @author   Kazuhiko Hasegawa
037 * @since    JDK5.0,
038 */
039public class Selection_CODE extends Selection_NULL {
040        private final CodeData  codeData ;
041
042        private final int[]             ADRS ;
043        private final String    CACHE ;
044        private final int               LEN ;
045
046        private final int[]             LADRS ;         // 5.1.3.0 (2010/02/01)
047        private final String    LCACHE ;        // 5.1.3.0 (2010/02/01)
048        private final int               LLEN ;          // 5.1.3.0 (2010/02/01)
049
050        private final String addKeyLabel ;      // 6.2.0.0 (2015/02/27) キー:ラベル形式
051
052        /**
053         * コンストラクター
054         *
055         * @og.rev 4.0.0.0 (2007/11/07) コードリソースの有無はDBColumnでチェックする。
056         * @og.rev 4.3.8.0 (2009/08/01) ツールチップ表示機能追加
057         * @og.rev 5.1.3.0 (2010/02/01) 一覧表示以外は、ツールチップ表示しない
058         * @og.rev 5.1.9.0 (2010/08/01) グループ機能とパラメータ機能の追加
059         * @og.rev 5.6.8.2 (2013/09/20) ツールチップは未加工のlongLabelを利用に修正
060         * @og.rev 5.7.7.1 (2014/06/13) Selection_NULL を 継承するため、super( null ); を追加します。
061         * @og.rev 6.2.0.0 (2015/02/27) コードリソースのパラメータの指定方法を変更します。
062         * @og.rev 6.2.0.0 (2015/02/27) キー:ラベル形式で表示するかどうかを、指定できるようにします。
063         * @og.rev 6.2.2.0 (2015/03/27) BRと\nを相互に変換する処理を追加
064         * @og.rev 6.2.2.3 (2015/04/10) htmlフィルターに、BR→改行処理機能を追加。
065         * @og.rev 6.7.7.1 (2017/04/07) コードリソースに概要を記入すると、isUse が無効になっていたのを修正。
066         *
067         * @param       cdData  コードデータオブジェクト
068         * @param       addKeyLabel キー:ラベル形式で表示するかどうか[true/false/null]
069         */
070        public Selection_CODE( final CodeData cdData,final String addKeyLabel ) {
071                super();                // 6.4.1.1 (2016/01/16) PMD refactoring. It is a good practice to call super() in a constructor
072                codeData = cdData ;
073                this.addKeyLabel = addKeyLabel;                 // 6.2.0.0 (2015/02/27) キー:ラベル形式
074                final int size = codeData.getSize();
075
076                // 5.1.9.0 (2010/08/01) グループ機能とパラメータの判定
077                final boolean isLbl = codeData.useLevel();
078                final boolean isCls = codeData.useParam();
079                boolean isLblSet = false;                               // optgroup の設定に使う。
080
081                ADRS  = new int[size];
082                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
083                boolean useTitle = false;                                                               // 4.3.8.0 (2009/08/01) title属性付加フラグ
084                for( int i=0; i<size; i++ ) {
085                        if( ! codeData.isUse(i) ) { continue; }
086
087                        // 6.2.0.0 (2015/02/27) キー:ラベル形式
088                        final String cdkey = codeData.getCodeKey(i);
089                        final String kv = "true".equalsIgnoreCase( addKeyLabel ) ? cdkey + ':' : "" ;
090                        final String rslbl = codeData.getRawShortLabel(i);
091
092                        // 5.1.9.0 (2010/08/01) コードレベルの判定
093                        if( isLbl && "0".equals( codeData.getCodeLevel(i) ) ) {
094                                if( isLblSet ) { buf.append( "</optgroup>" ); }
095
096                                // 8.5.4.2 (2024/01/12) PMD 7.0.0 InefficientStringBuffering 対応
097//                              buf.append( "<optgroup label=\"" + rslbl + "\">" );
098                                buf.append( "<optgroup label=\"" ).append( rslbl ).append( "\">" );
099                                isLblSet = true;
100                                continue;
101                        }
102
103                        // 6.0.2.5 (2014/10/31) char を append する。
104                        // 6.2.0.0 (2015/02/27) キー:ラベル形式
105                        buf.append( "<option value=\"" ).append( cdkey ).append( '"' );
106                        ADRS[i] = buf.length() ;
107
108                        // 5.1.9.0 (2010/08/01) パラメータの利用
109                        if( isCls ) {
110                                // 6.2.0.0 (2015/02/27) コードリソースのパラメータの指定方法を変更します。
111                                final String paramKey = codeData.getCodeParam(i);
112                                setCodeParam( buf,paramKey );
113                        }
114
115                        // 6.2.0.0 (2015/02/27) Description があれば、優先して title 属性に設定します。
116                        final String desc = codeData.getDescription(i);
117                        if( desc.isEmpty() ) {
118                                // 4.3.8.0 (2009/08/01) LongLabelはRawShortLabelと異なるときにツールチップとして表示させる
119                                final String lblb  = codeData.getRawLongLabel(i); // 5.6.8.2 (2013/09/20) ここでは生の名称長を取る
120                                if( ! rslbl.equals( lblb ) ){
121                                        // 6.2.2.0 (2015/03/27) BRと\nを相互に変換する処理を追加
122                                        buf.append(" title=\"").append( StringUtil.htmlFilter( lblb,true ) ).append( '"' );
123                                        useTitle = true;
124                                }
125                        }
126                        else {
127                                // 6.2.2.0 (2015/03/27) BRと\nを相互に変換する処理を追加
128                                buf.append(" title=\"").append( StringUtil.htmlFilter( desc,true ) ).append( '"' );
129                                useTitle = true;
130                        }
131
132                        // ShortLabelをBODYにする。
133                        // 6.2.0.0 (2015/02/27) キー:ラベル形式
134                        buf.append( '>' ).append( kv ).append( rslbl ).append( "</option>" );
135                }
136                if( isLbl ) {
137                        buf.append( "</optgroup>" );
138                }
139
140                CACHE = buf.toString();
141                LEN   = CACHE.length() + 30;
142
143                // 5.1.3.0 (2010/02/01) ツールチップ表示が適用されている場合のみ、ツールチップなしの状態のoptionをキャッシュする。
144                if( useTitle ) {
145                        isLblSet = false;
146
147                        LADRS  = new int[size];
148                        final StringBuilder lbuf = new StringBuilder( BUFFER_MIDDLE );
149                        for( int i=0; i<size; i++ ) {
150                                if( ! codeData.isUse(i) ) { continue; }         // 6.7.7.1 (2017/04/07)
151
152                                // 6.2.0.0 (2015/02/27) キー:ラベル形式
153                                final String cdkey = codeData.getCodeKey(i);
154                                final String kv = "true".equalsIgnoreCase( addKeyLabel ) ? (cdkey + ':') : "" ;
155                                final String lblb  = codeData.getLongLabel(i);
156                                // 5.1.9.0 (2010/08/01) グループ機能の判定
157                                if( isLbl && "0".equals( codeData.getCodeLevel(i) ) ) {
158                                        if( isLblSet ) { lbuf.append( "</optgroup>" ); }
159
160                                        // 8.5.4.2 (2024/01/12) PMD 7.0.0 InefficientStringBuffering 対応
161//                                      lbuf.append( "<optgroup label=\"" + lblb + "\">" );
162                                        lbuf.append( "<optgroup label=\"" ).append( lblb ).append( "\">" );
163                                        isLblSet = true;
164                                        continue;
165                                }
166
167                                // 6.0.2.5 (2014/10/31) char を append する。
168                                // 6.2.0.0 (2015/02/27) キー:ラベル形式
169                                lbuf.append( "<option value=\"" ).append( cdkey ).append( '"' );
170                                LADRS[i] = lbuf.length() ;
171
172                                // 5.1.9.0 (2010/08/01) パラメータの利用
173                                if( isCls ) {
174                                        // 6.2.0.0 (2015/02/27) コードリソースのパラメータの指定方法を変更します。
175                                        final String paramKey = codeData.getCodeParam(i);
176                                        setCodeParam( lbuf,paramKey );
177                                }
178
179                                // 6.2.0.0 (2015/02/27) キー:ラベル形式
180                                lbuf.append( '>' ).append( kv ).append( lblb ).append( "</option>" );
181                        }
182                        if( isLbl ) {
183                                buf.append( "</optgroup>" );
184                        }
185
186                        LCACHE = lbuf.toString();
187                        LLEN   = LCACHE.length() + 30;
188                }
189                else {
190                        LADRS  = ADRS;
191                        LCACHE = CACHE;
192                        LLEN   = LEN;
193                }
194        }
195
196        /**
197         * 初期値が選択済みの 選択肢(オプション)を返します。
198         * このオプションは、引数の値を初期値とするオプションタグを返します。
199         * このメソッドでは、引数のuseShortLabelがtrueに指定された場合に、ラベル(短)をベースとした
200         * ツールチップ表示を行います。
201         *
202         * @og.rev 5.1.3.0 (2010/02/01) 追加
203         *
204         * @param   selectValue  選択されている値
205         * @param   seqFlag  シーケンスアクセス機能 [true:ON/false:OFF]
206         * @param   useShortLabel ラベル(短)をベースとしたオプション表示を行うかどうか。
207         *
208         * @return  オプションタグ
209         * @og.rtnNotNull
210         */
211        @Override
212        public String getOption( final String selectValue,final boolean seqFlag, final boolean useShortLabel ) {
213                int[] adrs = null;
214                String cache = null;
215                int len = 0;
216                if( useShortLabel ) {
217                        adrs  = ADRS;
218                        cache = CACHE;
219                        len   = LEN;
220                }
221                else {
222                        adrs  = LADRS;
223                        cache = LCACHE;
224                        len   = LLEN;
225                }
226
227                // 8.5.5.1 (2024/02/29) PMD 7.0.0 OnlyOneReturn メソッドには終了ポイントが 1 つだけ必要
228                final String rtn;
229
230                // マッチするアドレスを探す。
231                final int selected = codeData.getAddress( selectValue );
232                if( selected < 0 ) {
233                        // 4.0.0 (2005/01/31)
234                        if( selectValue != null && selectValue.length() > 0 ) {
235                                final String errMsg = "コードに存在しない値が指定されました。"
236                                                        + " value=[" + selectValue + "]"
237                                                        + CR + codeData ;
238                                LogWriter.log( errMsg );
239                        }
240//                      return cache;
241                        rtn = cache;
242                }
243                else {
244                        final StringBuilder buf = new StringBuilder( len + 100 );                                               // 6.1.0.0 (2014/12/26) refactoring
245                        // 3.6.0.6 (2004/10/22) シーケンスアクセス機能を指定する seqFlag を導入
246                        if( seqFlag ) {
247                                buf.append( "<option value=\"" ).append( codeData.getCodeKey(selected) ).append( '"' );         // 6.0.2.5 (2014/10/31) char を append する。
248                        }
249                        else {
250                                buf.append( cache.substring( 0,adrs[selected] ) );
251                        }
252                        buf.append( " selected=\"selected\"" )
253                                .append( cache.substring( adrs[selected] ) );
254//                      return buf.toString() ;
255                        rtn = buf.toString() ;
256                }
257                return rtn;
258        }
259
260        /**
261         * 選択肢(value)に対するラベルを返します。
262         * 選択肢(value)が、存在しなかった場合は、選択肢そのものを返します。
263         * このメソッドでは、短縮ラベルを返すかどうかを指定するフラグを指定します。
264         * getValueLabel( XX,false ) は、getValueLabel( XX ) と同じです。
265         *
266         * @og.rev 4.0.0.0 (2005/11/30) を追加
267         * @og.rev 6.2.0.0 (2015/02/27) キー:ラベル形式で表示するかどうかを、指定できるようにします。
268         *
269         * @param       selectValue     選択肢の値
270         * @param       isSLbl  短縮ラベル使用可否 [true:使用する/false:しない]
271         *
272         * @return  選択肢のラベル
273         * @see     #getValueLabel( String )
274         */
275        @Override
276        public String getValueLabel( final String selectValue,final boolean isSLbl ) {
277                // 8.5.5.1 (2024/02/29) PMD 7.0.0 OnlyOneReturn メソッドには終了ポイントが 1 つだけ必要
278                final String rtn;
279
280                // マッチするアドレスを探す。
281                final int selected = codeData.getAddress( selectValue );
282                if( selected < 0 ) {
283                        // マッチしなければ、選択肢そのものを返す。
284//                      return selectValue;
285                        rtn = selectValue;
286                }
287                else {
288                        // 6.2.0.0 (2015/02/27) キー:ラベル形式
289                        final String lbl = isSLbl ? codeData.getShortLabel(selected) : codeData.getLongLabel(selected);
290
291//                      return "true".equalsIgnoreCase( addKeyLabel ) ? selectValue + ':' + lbl : lbl ;
292                        rtn = "true".equalsIgnoreCase( addKeyLabel ) ? (selectValue + ':' + lbl) : lbl ;
293                }
294                return rtn;
295        }
296
297}