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.plugin.table;
017
018import java.util.stream.Stream;                                                                 // 7.3.1.1 (2021/02/25)
019import java.util.stream.Collectors;                                                             // 7.3.1.1 (2021/02/25)
020
021import org.opengion.hayabusa.db.AbstractTableFilter;
022import org.opengion.hayabusa.db.DBTableModel;
023import org.opengion.hayabusa.resource.ResourceFactory;
024import org.opengion.hayabusa.resource.ResourceManager;
025import org.opengion.fukurou.util.ErrorMessage;
026import org.opengion.fukurou.util.StringUtil;
027
028/**
029 * TableFilter_LABEL は、TableFilter インターフェースを継承した、DBTableModel 処理用の
030 * 実装クラスです。
031 *
032 * ここでは、キーのCLM,LBL と、LANG より、ラベルリソースに変換した値を設定します。
033 * ラベルの設定は、設定先の値が NULL/空文字か、カラム名と同じ(無変換セット)の場合のみセットされます。
034 *
035 * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか、BODY 部にCSS形式で記述します。
036 * 【パラメータ】
037 *  {
038 *       SYSTEM_ID  : ラベルリソースの作成システムIDを指定します。無指定時は、ログイン時のリソースになります。
039 *       LANG       : ラベルリソースの言語を指定します。無指定時は、日本語になります。
040 *       CLM        : ラベルリソースのキーとなる値が設定されているカラム名を指定します。
041 *       LBL        : CLMで指定されたカラム名から値を取り出し、ラベルリソースに変換した結果をセットします。
042 *       LLBL       : 同上(ラベル長)                                                                  7.2.9.0 (2020/10/12)
043 *       SLBL       : 同上(ラベル短)                                                                  7.2.9.0 (2020/10/12)
044 *       DISC       : 同上(概要)                                                                            7.2.9.0 (2020/10/12)
045 *       LRAW       : 同上(長生ラベル)                                                         7.2.9.0 (2020/10/12)
046 *       SRAW       : 同上(短生ラベル)                                                         7.2.9.0 (2020/10/12)
047 *       MSG        : 同上(引数付きラベル)                                                       7.2.9.1 (2020/10/23)
048 *       USE_CSV    : true:CLMの設定値がCSV形式/false:通常の単独カラム         7.3.1.1 (2021/02/25)
049 *  }
050 *
051 * 5.7.8.0 (2014/07/04) 解除
052 * CLM と LBL に同じカラムを指定すると、このフィルターを通過するたびに、変換後のラベルが
053 * 再びキーとして変換しようと試みることになります。不測の事態に陥る可能性があるため、
054 * その様な設定は出来なくなっています。
055 *
056 * 5.7.8.0 (2014/07/04) CLM と LBL に同じカラムを指定する事ができます。
057 *
058 * また、CLM または LBL で指定したカラムが DBTableModel に存在しない場合は、処理そのものを
059 * 無視します。その場合は、警告も出力されませんので、ご注意ください。
060 *
061 * 7.2.9.0 (2020/10/12) LLBL,SLBL,DISC,RLBL 属性追加。
062 *
063 * 7.2.9.1 (2020/10/23) MSG 属性追加。
064 *   引数付きなので、VALS 指定時に、セットするカラム名に引数として渡したいパラメータをスペースで繋げます。
065 *   パラメータは、@カラム名 か、そのままの値で指定します。
066 *
067 * 7.3.1.1 (2021/02/25) USE_CSV 属性追加。
068 *   true:CLMの設定値がCSV形式/false:通常の単独カラム
069 *   ただし、LRAW,SRAW,MSG については、変換しません。
070 *
071 * @og.formSample
072 * ●形式:
073 *      ① <og:tableFilter classId="LABEL" keys="CLM,LBL" vals="COLUMN,LABEL_CLM" />
074 *
075 *      ② <og:tableFilter classId="LABEL" >
076 *               {
077 *                      SYSTEM_ID  : GF ;
078 *                      LANG       : ja ;
079 *                      CLM        : COLUMN ;
080 *                      LBL        : LABEL_CLM ;
081 *               }
082 *         </og:tableFilter>
083 *
084 * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを追加
085 *
086 * @version  0.9.0  2000/10/17
087 * @author   Kazuhiko Hasegawa
088 * @since    JDK1.1,
089 */
090public class TableFilter_LABEL extends AbstractTableFilter {
091        /** このプログラムのVERSION文字列を設定します。   {@value} */
092        private static final String VERSION = "7.3.1.1 (2021/02/25)" ;
093
094        /**
095         * デフォルトコンストラクター
096         *
097         * @og.rev 6.4.1.1 (2016/01/16) keysMap を、サブクラスから設定させるように変更。
098         */
099        public TableFilter_LABEL() {
100                super();
101                initSet( "SYSTEM_ID"    , "システムIDを指定します(初期値:ログイン時のリソース)"                );
102                initSet( "LANG"                 , "言語を指定(初期値:日本語)"                                                              );
103                initSet( "CLM"                  , "キーとなる値が設定されているカラム名を指定"                               );
104                initSet( "LBL"                  , "ラベルリソースに変換した結果をセットするカラム名を指定" );
105                initSet( "LLBL"                 , "同上(ラベル長)"                                                                            );              // 7.2.9.0 (2020/10/12)
106                initSet( "SLBL"                 , "同上(ラベル短)"                                                                            );              // 7.2.9.0 (2020/10/12)
107                initSet( "DISC"                 , "同上(概要)       "                                                                                       );              // 7.2.9.0 (2020/10/12)
108                initSet( "LRAW"                 , "同上(長生ラベル)"                                                                           );              // 7.2.9.0 (2020/10/12)
109                initSet( "SRAW"                 , "同上(短生ラベル)"                                                                           );              // 7.2.9.0 (2020/10/12)
110                initSet( "MSG"                  , "同上(引数付きラベル)"                                                                 );              // 7.2.9.1 (2020/10/23)
111                initSet( "USE_CSV"              , "true:CLMの設定値がCSV形式/false:通常の単独カラム"                   );              // 7.3.1.1 (2021/02/25)
112        }
113
114        /**
115         * DBTableModel処理を実行します。
116         *
117         * @og.rev 5.5.2.2 (2012/05/09) SYSTEM_ID を受け取るように変更
118         * @og.rev 5.5.2.6 (2012/05/25) protected変数を、private化したため、getterメソッドで取得するように変更
119         * @og.rev 5.7.8.0 (2014/07/04) CLM と LBL に同じカラムを指定できるように変更
120         * @og.rev 6.4.0.5 (2016/01/09) LBLが、nullか、または、CLMと同じ場合は、リソースから、そうでない場合は、LBLの値を使用します。
121         * @og.rev 6.5.0.1 (2016/10/21) ErrorMessage をまとめるのと、直接 Throwable を渡します。
122         * @og.rev 7.2.9.0 (2020/10/12) LLBL,SLBL,DISC,RLBL 属性追加
123         * @og.rev 7.2.9.1 (2020/10/23) MSG 属性追加
124         * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加
125         *
126         * @return 処理結果のDBTableModel
127         */
128        public DBTableModel execute() {
129                final DBTableModel table = getDBTableModel();                   // 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加
130
131                if( table == null ) { return table; }                                   // 6.4.0.5 (2016/01/09)
132
133                final String systemId   = getValue( "SYSTEM_ID" );              // 5.5.2.2 (2012/05/09)
134                final String lang               = getValue( "LANG" );
135                final ResourceManager resource = ResourceFactory.newInstance( systemId,lang,false );            // 5.5.2.2 (2012/05/09)
136
137                final String clm  = getValue( "CLM" );
138                final String lbl  = getValue( "LBL" );
139                final String llbl = getValue( "LLBL" );                                         // 7.2.9.0 (2020/10/12)
140                final String slbl = getValue( "SLBL" );                                         // 7.2.9.0 (2020/10/12)
141                final String disc = getValue( "DISC" );                                         // 7.2.9.0 (2020/10/12)
142                final String lraw = getValue( "LRAW" );                                         // 7.2.9.0 (2020/10/12)
143                final String sraw = getValue( "SRAW" );                                         // 7.2.9.0 (2020/10/12)
144
145                final boolean useCSV = StringUtil.nval( getValue( "USE_CSV" ),false );  // 7.3.1.1 (2021/02/25)
146
147                final int clmNo   = table.getColumnNo( clm,false );                     // 存在しない場合は、-1 を返す。
148                final int lblNo   = table.getColumnNo( lbl,false );
149                final int llblNo  = table.getColumnNo( llbl,false );            // 7.2.9.0 (2020/10/12)
150                final int slblNo  = table.getColumnNo( slbl,false );            // 7.2.9.0 (2020/10/12)
151                final int discNo  = table.getColumnNo( disc,false );            // 7.2.9.0 (2020/10/12)
152                final int lrawNo  = table.getColumnNo( lraw,false );            // 7.2.9.0 (2020/10/12)
153                final int srawNo  = table.getColumnNo( sraw,false );            // 7.2.9.0 (2020/10/12)
154
155                // 7.2.9.1 (2020/10/23) MSGの値は、セットするカラム名の後ろに、パラメータをスペースで繋げています。
156                final String msg_prm = getValue( "MSG" );
157                final int   msgNo ;
158                final int[] prmNo ;
159                final String[] prmVal ;
160
161                if( msg_prm != null ) {
162                        final String[] msgs = msg_prm.split( "[\\s]+" );                // 連続スペース、タブを区切り文字にする。
163                        msgNo = table.getColumnNo( msgs[0],false );
164                        prmNo  = new int[msgs.length-1];
165                        prmVal = new String[msgs.length-1];
166                        for( int i=1; i<msgs.length; i++ ) {
167                                prmVal[i-1] = msgs[i];                                                          // 元の引数をそのまま使う可能性があるので、セットしておく。
168
169                                if( '@' == msgs[i].charAt(0) ) {                                        // カラム指定の意味
170                                        prmNo[i-1] = table.getColumnNo( msgs[i].substring(1),false );
171                                }
172                                else {
173                                        prmNo[i-1] = -1;
174                                }
175                        }
176                }
177                else {
178                        msgNo  = -1;
179                        prmNo  = null;
180                        prmVal = null;
181                }
182
183                // 5.7.8.0 (2014/07/04) CLM と LBL に同じカラムを指定できるように変更
184//              if( clmNo >= 0 && lblNo >= 0 ) {
185//              if( clmNo >= 0 && ( lblNo >= 0 || llblNo >= 0 || slblNo >= 0 || discNo >= 0 || lrawNo >= 0 || srawNo >= 0 ) ) {                                 // 7.2.9.0 (2020/10/12)
186                if( clmNo >= 0 && ( lblNo >= 0 || llblNo >= 0 || slblNo >= 0 || discNo >= 0 || lrawNo >= 0 || srawNo >= 0 || msgNo >= 0 ) ) {   // 7.2.9.1 (2020/10/23)
187                        String[] data  = null;
188                        final int rowCnt = table.getRowCount();
189                        for( int row=0; row<rowCnt; row++ ) {
190                                String clmVal = null;
191                                try {
192                                        data   = table.getValues( row );
193                                        clmVal = data[clmNo];           // 変換する元のカラム名
194
195                                        if( lblNo >= 0 ) {
196                                                final String lblVal = data[lblNo];              // 変換する元のラベル            6.4.0.5 (2016/01/09)
197                                                // 6.4.0.5 (2016/01/09) LBLが、nullか、または、CLMと同じ場合は、リソースから、そうでない場合は、LBLの値を使用します。
198                                                // つまり、上記の条件が成立した場合は、LBLを書き換えないということです。
199                                                if( StringUtil.isNull( lblVal ) || lblVal.equals( clmVal ) ) {
200                                                        if( useCSV ) {                                          // 7.3.1.1 (2021/02/25)
201                                                                data[lblNo] = Stream.of( clmVal.split(",") )
202                                                                                                        .map( clmv -> resource.getLabel( clmv ) )
203                                                                                                        .collect( Collectors.joining( "," ) );
204                                                        }
205                                                        else {
206                                                                data[lblNo] = resource.getLabel( clmVal ) ;
207                                                        }
208                                                }
209                                        }
210
211                                        // 7.2.9.0 (2020/10/12) LLBL,SLBL,DISC,RLBL 属性追加
212                                        if( llblNo >= 0 ) {
213                                                final String llblVal = data[llblNo];            // 変換する元のラベル            6.4.0.5 (2016/01/09)
214                                                if( StringUtil.isNull( llblVal ) || llblVal.equals( clmVal ) ) {
215                                                        if( useCSV ) {                                          // 7.3.1.1 (2021/02/25)
216                                                                data[llblNo] = Stream.of( clmVal.split(",") )
217                                                                                                        .map( clmv -> resource.getLongLabel( clmv ) )
218                                                                                                        .collect( Collectors.joining( "," ) );
219                                                        }
220                                                        else {
221                                                                data[llblNo] = resource.getLongLabel( clmVal ) ;
222                                                        }
223                                                }
224                                        }
225
226                                        if( slblNo >= 0 ) {
227                                                final String slblVal = data[slblNo];            // 変換する元のラベル            6.4.0.5 (2016/01/09)
228                                                if( StringUtil.isNull( slblVal ) || slblVal.equals( clmVal ) ) {
229                                                        if( useCSV ) {                                          // 7.3.1.1 (2021/02/25)
230                                                                data[slblNo] = Stream.of( clmVal.split(",") )
231                                                                                                        .map( clmv -> resource.getShortLabel( clmv ) )
232                                                                                                        .collect( Collectors.joining( "," ) );
233                                                        }
234                                                        else {
235                                                                data[slblNo] = resource.getShortLabel( clmVal ) ;
236                                                        }
237                                                }
238                                        }
239
240                                        // 7.2.9.0 (2020/10/12) SLBL,DISC,RLBL 属性追加
241                                        if( discNo >= 0 ) {
242                                                final String discVal = data[discNo];            // 変換する元のラベル            6.4.0.5 (2016/01/09)
243                                                if( StringUtil.isNull( discVal ) || discVal.equals( clmVal ) ) {
244                                                        if( useCSV ) {                                          // 7.3.1.1 (2021/02/25)
245                                                                data[discNo] = Stream.of( clmVal.split(",") )
246                                                                                                        .map( clmv -> resource.getDescription( clmv ) )
247                                                                                                        .collect( Collectors.joining( "," ) );
248                                                        }
249                                                        else {
250                                                                data[discNo] = resource.getDescription( clmVal ) ;
251                                                        }
252                                                }
253                                        }
254
255                                        // 7.2.9.0 (2020/10/12) SLBL,DISC,RLBL 属性追加
256                                        if( lrawNo >= 0 ) {
257                                                final String lrawVal = data[lrawNo];            // 変換する元のラベル            6.4.0.5 (2016/01/09)
258                                                if( StringUtil.isNull( lrawVal ) || lrawVal.equals( clmVal ) ) {
259                                                        final String val = resource.getRawLongLabel( clmVal ) ;
260                                                        data[lrawNo] = val == null || val.equals( clmVal ) ? "" : val ;         // null時はkeyが返ってくるので 空文字 を返す。
261                                                }
262                                        }
263
264                                        // 7.2.9.0 (2020/10/12) SLBL,DISC,RLBL 属性追加
265                                        if( srawNo >= 0 ) {
266                                                final String srawVal = data[srawNo];            // 変換する元のラベル            6.4.0.5 (2016/01/09)
267                                                if( StringUtil.isNull( srawVal ) || srawVal.equals( clmVal ) ) {
268                                                        final String val = resource.getRawShortLabel( clmVal,false ) ;          // null時は 空文字 を返す。
269                                                        data[srawNo] = val == null || val.equals( clmVal ) ? "" : val;          // null時は 空文字 を返す。
270
271//                                                      data[srawNo] = resource.getRawShortLabel( clmVal,false ) ;                      // null時は 空文字 を返す。
272                                                }
273                                        }
274
275                                        // 7.2.9.1 (2020/10/23) MSG 属性追加
276                                        if( msgNo >= 0 ) {
277                                                final String msgVal = data[msgNo];
278                                                if( StringUtil.isNull( msgVal ) || msgVal.equals( clmVal ) ) {
279                                                        final String[] prmVals = new String[prmNo.length];
280                                                        for( int i=0; i<prmNo.length; i++ ) {
281                                                                if( prmNo[i] >= 0 ) {
282                                                                        prmVals[i] = StringUtil.nval( data[prmNo[i]] , "" );
283                                                                }
284                                                                else {
285                                                                        prmVals[i] = prmVal[i];
286                                                                }
287                                                        }
288
289                                                        data[msgNo] = resource.getLabel( clmVal,prmVals ) ;
290                                                }
291                                        }
292                                }
293                                catch( final RuntimeException ex ) {
294                                        // 6.5.0.1 (2016/10/21) ErrorMessage をまとめるのと、直接 Throwable を渡します。
295                                        makeErrorMessage( "TableFilter_LABEL Error",ErrorMessage.NG )
296                                                .addMessage( row+1,ErrorMessage.NG,"LABEL"
297                                                        , "CLM=[" + clm + "],VAL=[" + clmVal + "]"
298                                                        , StringUtil.array2csv( data )
299                                                )
300                                                .addMessage( ex );
301                                }
302                        }
303                }
304
305                return table;
306        }
307}