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                                buf.append( "<optgroup label=\"" + rslbl + "\">" );
097                                isLblSet = true;
098                                continue;
099                        }
100
101                        // 6.0.2.5 (2014/10/31) char を append する。
102                        // 6.2.0.0 (2015/02/27) キー:ラベル形式
103                        buf.append( "<option value=\"" ).append( cdkey ).append( '"' );
104                        ADRS[i] = buf.length() ;
105
106                        // 5.1.9.0 (2010/08/01) パラメータの利用
107                        if( isCls ) {
108                                // 6.2.0.0 (2015/02/27) コードリソースのパラメータの指定方法を変更します。
109                                final String paramKey = codeData.getCodeParam(i);
110                                setCodeParam( buf,paramKey );
111                        }
112
113                        // 6.2.0.0 (2015/02/27) Description があれば、優先して title 属性に設定します。
114                        final String desc = codeData.getDescription(i);
115                        if( desc.isEmpty() ) {
116                                // 4.3.8.0 (2009/08/01) LongLabelはRawShortLabelと異なるときにツールチップとして表示させる
117                                final String lblb  = codeData.getRawLongLabel(i); // 5.6.8.2 (2013/09/20) ここでは生の名称長を取る
118                                if( ! rslbl.equals( lblb ) ){
119                                        // 6.2.2.0 (2015/03/27) BRと\nを相互に変換する処理を追加
120                                        buf.append(" title=\"").append( StringUtil.htmlFilter( lblb,true ) ).append( '"' );
121                                        useTitle = true;
122                                }
123                        }
124                        else {
125                                // 6.2.2.0 (2015/03/27) BRと\nを相互に変換する処理を追加
126                                buf.append(" title=\"").append( StringUtil.htmlFilter( desc,true ) ).append( '"' );
127                                useTitle = true;
128                        }
129
130                        // ShortLabelをBODYにする。
131                        // 6.2.0.0 (2015/02/27) キー:ラベル形式
132                        buf.append( '>' ).append( kv ).append( rslbl ).append( "</option>" );
133                }
134                if( isLbl ) {
135                        buf.append( "</optgroup>" );
136                }
137
138                CACHE = buf.toString();
139                LEN   = CACHE.length() + 30;
140
141                // 5.1.3.0 (2010/02/01) ツールチップ表示が適用されている場合のみ、ツールチップなしの状態のoptionをキャッシュする。
142                if( useTitle ) {
143                        isLblSet = false;
144
145                        LADRS  = new int[size];
146                        final StringBuilder lbuf = new StringBuilder( BUFFER_MIDDLE );
147                        for( int i=0; i<size; i++ ) {
148                                if( ! codeData.isUse(i) ) { continue; }         // 6.7.7.1 (2017/04/07)
149
150                                // 6.2.0.0 (2015/02/27) キー:ラベル形式
151                                final String cdkey = codeData.getCodeKey(i);
152                                final String kv = "true".equalsIgnoreCase( addKeyLabel ) ? cdkey + ':' : "" ;
153                                final String lblb  = codeData.getLongLabel(i);
154                                // 5.1.9.0 (2010/08/01) グループ機能の判定
155                                if( isLbl && "0".equals( codeData.getCodeLevel(i) ) ) {
156                                        if( isLblSet ) { lbuf.append( "</optgroup>" ); }
157
158                                        lbuf.append( "<optgroup label=\"" + lblb + "\">" );
159                                        isLblSet = true;
160                                        continue;
161                                }
162
163                                // 6.0.2.5 (2014/10/31) char を append する。
164                                // 6.2.0.0 (2015/02/27) キー:ラベル形式
165                                lbuf.append( "<option value=\"" ).append( cdkey ).append( '"' );
166                                LADRS[i] = lbuf.length() ;
167
168                                // 5.1.9.0 (2010/08/01) パラメータの利用
169                                if( isCls ) {
170                                        // 6.2.0.0 (2015/02/27) コードリソースのパラメータの指定方法を変更します。
171                                        final String paramKey = codeData.getCodeParam(i);
172                                        setCodeParam( lbuf,paramKey );
173                                }
174
175                                // 6.2.0.0 (2015/02/27) キー:ラベル形式
176                                lbuf.append( '>' ).append( kv ).append( lblb ).append( "</option>" );
177                        }
178                        if( isLbl ) {
179                                buf.append( "</optgroup>" );
180                        }
181
182                        LCACHE = lbuf.toString();
183                        LLEN   = LCACHE.length() + 30;
184                }
185                else {
186                        LADRS  = ADRS;
187                        LCACHE = CACHE;
188                        LLEN   = LEN;
189                }
190        }
191
192        /**
193         * 初期値が選択済みの 選択肢(オプション)を返します。
194         * このオプションは、引数の値を初期値とするオプションタグを返します。
195         * このメソッドでは、引数のuseShortLabelがtrueに指定された場合に、ラベル(短)をベースとした
196         * ツールチップ表示を行います。
197         *
198         * @og.rev 5.1.3.0 (2010/02/01) 追加
199         *
200         * @param   selectValue  選択されている値
201         * @param   seqFlag  シーケンスアクセス機能 [true:ON/false:OFF]
202         * @param   useShortLabel ラベル(短)をベースとしたオプション表示を行うかどうか。
203         *
204         * @return  オプションタグ
205         * @og.rtnNotNull
206         */
207        @Override
208        public String getOption( final String selectValue,final boolean seqFlag, final boolean useShortLabel ) {
209                int[] adrs = null;
210                String cache = null;
211                int len = 0;
212                if( useShortLabel ) {
213                        adrs  = ADRS;
214                        cache = CACHE;
215                        len   = LEN;
216                }
217                else {
218                        adrs  = LADRS;
219                        cache = LCACHE;
220                        len   = LLEN;
221                }
222
223                // マッチするアドレスを探す。
224                final int selected = codeData.getAddress( selectValue );
225
226                if( selected < 0 ) {
227                        // 4.0.0 (2005/01/31)
228                        if( selectValue != null && selectValue.length() > 0 ) {
229                                final String errMsg = "コードに存在しない値が指定されました。"
230                                                        + " value=[" + selectValue + "]"
231                                                        + CR + codeData ;
232                                LogWriter.log( errMsg );
233                        }
234                        return cache;
235                }
236                else {
237                        final StringBuilder buf = new StringBuilder( len + 100 );                                               // 6.1.0.0 (2014/12/26) refactoring
238                        // 3.6.0.6 (2004/10/22) シーケンスアクセス機能を指定する seqFlag を導入
239                        if( seqFlag ) {
240                                buf.append( "<option value=\"" ).append( codeData.getCodeKey(selected) ).append( '"' );         // 6.0.2.5 (2014/10/31) char を append する。
241                        }
242                        else {
243                                buf.append( cache.substring( 0,adrs[selected] ) );
244                        }
245                        buf.append( " selected=\"selected\"" )
246                                .append( cache.substring( adrs[selected] ) );
247                        return buf.toString() ;
248                }
249        }
250
251        /**
252         * 選択肢(value)に対するラベルを返します。
253         * 選択肢(value)が、存在しなかった場合は、選択肢そのものを返します。
254         * このメソッドでは、短縮ラベルを返すかどうかを指定するフラグを指定します。
255         * getValueLabel( XX,false ) は、getValueLabel( XX ) と同じです。
256         *
257         * @og.rev 4.0.0.0 (2005/11/30) を追加
258         * @og.rev 6.2.0.0 (2015/02/27) キー:ラベル形式で表示するかどうかを、指定できるようにします。
259         *
260         * @param       selectValue     選択肢の値
261         * @param       isSLbl  短縮ラベル使用可否 [true:使用する/false:しない]
262         *
263         * @return  選択肢のラベル
264         * @see     #getValueLabel( String )
265         */
266        @Override
267        public String getValueLabel( final String selectValue,final boolean isSLbl ) {
268                // マッチするアドレスを探す。
269                final int selected = codeData.getAddress( selectValue );
270
271                if( selected < 0 ) {
272                        // マッチしなければ、選択肢そのものを返す。
273                        return selectValue;
274                }
275                else {
276                        // 6.2.0.0 (2015/02/27) キー:ラベル形式
277                        final String lbl = isSLbl ? codeData.getShortLabel(selected) : codeData.getLongLabel(selected);
278
279                        return "true".equalsIgnoreCase( addKeyLabel ) ? selectValue + ':' + lbl : lbl ;
280                }
281        }
282
283}