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     */
016    package org.opengion.plugin.table;
017    
018    import org.opengion.hayabusa.db.AbstractTableFilter;
019    import org.opengion.hayabusa.db.DBTableModel;
020    import org.opengion.hayabusa.db.DBColumn;
021    
022    import org.opengion.hayabusa.resource.ResourceFactory;
023    import org.opengion.hayabusa.resource.ResourceManager;
024    import org.opengion.hayabusa.resource.CodeData;
025    
026    import org.opengion.fukurou.util.ErrorMessage;
027    import org.opengion.fukurou.util.StringUtil;
028    
029    import java.util.Locale;
030    import java.util.Map;
031    
032    /**
033     * TableFilter_CLMSET は、TableFilter インターフェースを継承した、DBTableModel 処?の
034     * 実?ラスです?
035     *
036     * ここでは、CLM,SYSTEM_ID,LANG より、カラ?ソースのRENDERER,EDITOR,DBTYPE,BIKOを設定します?
037     * 検索した DBTableModel の属?として、RENDERER,EDITOR,DBTYPE,BIKO と?名称の
038     * カラ??です?
039     * 引数として?可能なのは、SYSTEM_ID,LANG のみです?
040     *  CLM :カラ?ソースのキーとなる?が設定されて?カラ?を指定します?
041     *  SYSTEM_ID:コードリソースの作?シス?IDを指定します?無?時は、ログイン時?リソースになります?
042     *  LANG:ラベルリソースの?を?します?無?時は、日本語になります?
043     *  USE_RESOURCE:リソース??を利用するかど?[true/false]。無?時は、true:利用するになります?
044     *
045     * また?CLM,RENDERER,EDITOR,DBTYPE,BIKO,CLS_NAME,USE_LENGTH で?したカラ? DBTableModel に存在しな??合??
046     * 処?のも?を無視します?そ?場合?、警告も出力されませんので、ご注意く???
047     *
048     * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか?BODY 部にCSS形式で記述します?
049     * 【パラメータ?
050     *  {
051     *       USE_RESOURCE   : [true/false] ;    リソースを利用するかど?を指定[true/false](初期値:true)。使??合?DBColumnを構築し、そこか?RENDERE 等を取得します?
052     *       CLM            : CLM ;             カラ?ソースのキーとなる?が設定されて?カラ?を指定します?
053     *       SYSTEM_ID      : GF ;              リソースを使??合に、コードリソースの作?シス?IDを指定します?
054     *       LANG           : ja ;              リソースを使??合に、ラベルリソースの?を?します?
055     *       RENDERER       : 設定するカラ?
056     *       EDITOR         : 設定するカラ?
057     *       DBTYPE         : 設定するカラ?
058     *       BIKO           : 設定するカラ?
059     *       CLS_NAME       : 設定するカラ?
060     *       USE_LENGTH     : 設定するカラ?
061     *  }
062     *
063     * @og.formSample
064     * ●形式?
065     *      ?<og:tableFilter classId="CLMSET" keys="USE_RESOURCE,CLM,SYSTEM_ID,RENDERER,EDITOR,DBTYPE,BIKO,CLS_NAME,USE_LENGTH"
066     *                                             vals="true,CLM,SYSTEM_ID,RENDERER,EDITOR,DBTYPE,BIKO,CLS_NAME,USE_LENGTH" />
067     *
068     *      ② <og:tableFilter classId="CLMSET" >
069     *               {
070     *                       USE_RESOURCE   : [true/false] ;    リソースを利用するかど?を指定[true/false](初期値:true)。使??合?DBColumnを構築し、そこか?RENDERE 等を取得します?
071     *                       CLM            : CLM ;             カラ?ソースのキーとなる?が設定されて?カラ?を指定します?
072     *                       SYSTEM_ID      : GF ;              リソースを使??合に、コードリソースの作?シス?IDを指定します?
073     *                       LANG           : ja ;              リソースを使??合に、ラベルリソースの?を?します?
074     *                       RENDERER       : 設定するカラ?
075     *                       EDITOR         : 設定するカラ?
076     *                       DBTYPE         : 設定するカラ?
077     *                       BIKO           : 設定するカラ?
078     *                       CLS_NAME       : 設定するカラ?
079     *                       USE_LENGTH     : 設定するカラ?
080     *               }
081     *         </og:tableFilter>
082     *
083     * @og.rev 4.1.0.0(2008/01/18) 新規作?
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.5,
089     */
090    public class TableFilter_CLMSET extends AbstractTableFilter {
091            //* こ?プログラ??VERSION??を設定します?       {@value} */
092            private static final String VERSION = "5.6.6.1 (2013/07/12)" ;
093    
094            /**
095             * keys の整合?チェ?を行うための初期設定を行います?
096             *
097             * @og.rev 5.6.6.1 (2013/07/12) keys の整合?チェ?対?
098             *
099             * @param       keysMap keys の整合?チェ?を行うための Map
100             */
101            @Override
102            protected void init( final Map<String,String> keysMap ) {
103                    keysMap.put( "USE_RESOURCE" , "リソースを利用するかど?を指定[true/false](初期値:true)"      );
104                    keysMap.put( "CLM"                      , "カラ?ソースのキーとなる?が設定されて?カラ?を指?  );
105                    keysMap.put( "SYSTEM_ID"        , "リソースを使??合に、コードリソースの作?シス?IDを指?  );
106                    keysMap.put( "LANG"             , "リソースを使??合に、ラベルリソースの?を??                  );
107                    keysMap.put( "RENDERER"         , "設定するカラ?"                                                                                       );
108                    keysMap.put( "EDITOR"           , "設定するカラ?"                                                                                       );
109                    keysMap.put( "DBTYPE"           , "設定するカラ?"                                                                                       );
110                    keysMap.put( "BIKO"             , "設定するカラ?"                                                                                       );
111                    keysMap.put( "CLS_NAME"         , "設定するカラ?"                                                                                       );
112                    keysMap.put( "USE_LENGTH"       , "設定するカラ?"                                                                                       );
113            }
114    
115            /**
116             * DBTableModel処?実行します?
117             *
118             * @og.rev 5.5.2.6 (2012/05/25) protected変数を?private化したため?getterメソ?で取得するよ?変更
119             * @og.rev 5.5.7.4 (2012/10/25) 備???処??、ここでは行いません?
120             * @og.rev 5.5.8.2 (2012/11/09) RENDERER,EDITOR,DBTYPE の条件?を変更します?
121             * @og.rev 5.5.8.5 (2012/11/27) USE_RESOURCE 引数追?
122             *
123             * @return 処?果のDBTableModel
124             */
125            public DBTableModel execute() {
126                    DBTableModel table = getDBTableModel();         // 5.5.2.6 (2012/05/25) インターフェースにgetterメソ?追?
127    
128                    boolean useResource = StringUtil.nval( getValue("USE_RESOURCE"), true );                // 5.5.8.5 (2012/11/27) USE_RESOURCE 引数追?
129    
130                    // 5.5.8.5 (2012/11/27) 初期化タイミングを遅らします?
131    //              String systemId = getValue( "SYSTEM_ID" );
132    //              String lang             = getValue( "LANG" );
133    //              ResourceManager resource = ResourceFactory.newInstance( systemId,lang,false );
134                    ResourceManager resource = null;
135    
136                    if( useResource ) {
137                            String systemId = getValue( "SYSTEM_ID" );
138                            String lang             = getValue( "LANG" );
139                            resource = ResourceFactory.newInstance( systemId,lang,false );
140                    }
141    
142                    int clmNo  = table.getColumnNo( "CLM",false );          // 存在しな??合??1 を返す?
143                    int renNo  = table.getColumnNo( "RENDERER",false );
144                    int ediNo  = table.getColumnNo( "EDITOR",false );
145                    int typNo  = table.getColumnNo( "DBTYPE",false );
146                    int bikoNo = table.getColumnNo( "BIKO",false );
147    
148                    int clsNo  = table.getColumnNo( "CLS_NAME",false );                     // 5.5.7.4 (2012/10/25) CLS_NAME カラ?号の取?
149                    int lenNo  = table.getColumnNo( "USE_LENGTH",false );           // 5.5.7.4 (2012/10/25) USE_LENGTH カラ?号の取?
150    
151    //              if( clmNo >= 0 && renNo >= 0 && ediNo >= 0 && typNo >= 0 && bikoNo >= 0 ) {              // 5.5.7.4 (2012/10/25) BIKO の設定?、??から外す
152                    if( clmNo >= 0 && renNo >= 0 && ediNo >= 0 && typNo >= 0 ) {
153                            String[] data  = null;
154                            int rowCnt = table.getRowCount();
155                            DBColumn column = null ;
156    //                      CodeData code ;
157                            for( int row=0; row<rowCnt; row++ ) {
158                                    String clmVal = null;
159                                    try {
160                                            data   = table.getValues( row );
161                                            clmVal = data[clmNo].trim().toUpperCase(Locale.JAPAN);          // 変換する??カラ?
162                                            // 5.5.8.5 (2012/11/27) USE_RESOURCE 引数追??
163                                            if( useResource ) {
164                                                    column = resource.getDBColumn( clmVal );
165                                            }
166                                            // 以下?設定?、副作用を及ぼして?す?注?
167                                            if( column != null ) {
168                                                    data[renNo] = column.getRenderer() ;
169                                                    data[ediNo] = column.getEditor() ;
170                                                    data[typNo] = column.getDbType() ;
171    
172                                                    // 5.5.7.4 (2012/10/25) BIKO の設定?、検索時にカラ?あり、MENUレン?ーで、備?NULLの場合?み再設定する?
173                                                    if( bikoNo >= 0 && "MENU".equalsIgnoreCase( data[renNo] ) && ( data[bikoNo] == null || data[bikoNo].isEmpty() ) ) {
174                                                            CodeData code = resource.getCodeData( clmVal );
175                                                            if( code != null ) {
176                                                                    data[bikoNo] = code.toCodeString() ;
177                                                            }
178                                                    }
179    
180                                                    // 本当?、RENDERER='MENU' の場合?み有効?
181    //                                              code = resource.getCodeData( clmVal );
182    //                                              if( code != null ) {
183    //                                                      data[bikoNo] = code.toCodeString() ;
184    //                                              }
185    //                                              // オブジェクトが存在しな??合?、クリアします?
186    //                                              else {
187    //                                                      data[bikoNo] = "";
188    //                                              }
189                                            }
190                                            // 5.5.7.4 (2012/10/25) オブジェクトが存在しな??合?、?動的に類似の??を設定します?
191    //                                      else {
192    //                                              data[renNo]  = "";
193    //                                              data[ediNo]  = "";
194    //                                              data[typNo]  = "";
195    //                                              data[bikoNo] = "";
196    //                                              if( clsNo >= 0 && data[clsNo] != null ) {
197    //                                                      if( "NUMBER".equalsIgnoreCase( data[clsNo] ) ) {
198    //                                                              data[renNo]  = "NUMBER";
199    //                                                              data[ediNo]  = "TEXT";
200    //                                                              data[typNo]  = "S9";
201    //                                                      }
202    //                                                      else if( data[clsNo].startsWith( "VARCHAR" ) ) {
203    //                                                              data[renNo]  = "LABEL";
204    //                                                              data[ediNo]  = "TEXT";
205    //                                                              data[typNo]  = "X";
206    //                                                              if( lenNo >= 0 && data[lenNo] != null && data[lenNo].length() >= 2 ) {
207    //                                                                      if( Integer.parseInt( data[lenNo] ) >= 30 ) {
208    //                                                                              data[typNo]  = "KX";                                            // 30ケタ以上?場合?、KX とする?
209    //                                                                      }
210    //                                                              }
211    //                                                      }
212    //                                              }
213    //                                      }
214                                            // 5.5.8.2 (2012/11/09) RENDERER,EDITOR,DBTYPE の条件?を変更します?
215                                            else {
216                                                    String clsVal  = (clsNo  < 0 || data[clsNo]  == null ) ? "" : data[clsNo].trim().toUpperCase(Locale.JAPAN);
217                                                    String lenVal  = (lenNo  < 0 || data[lenNo]  == null ) ? "" : data[lenNo].trim().replace( '.',',' ) ;
218                                                    String bikoVal = (bikoNo < 0 || data[bikoNo] == null ) ? "" : data[bikoNo];
219    
220                                                    // 長さで、小数部が? 0 の場合?、整数のみと判断する?
221                                                    int cm = lenVal.indexOf( ",0" );
222                                                    if( cm >= 0 ) { lenVal = lenVal.substring( 0,cm ); }
223    
224                                                    String[] selData = serchMasterData( clmVal,clsVal,lenVal,bikoVal );
225    
226                                                    // 副作用を及ぼします?
227                                                    data[renNo]  = selData[NO_REN];
228                                                    data[ediNo]  = selData[NO_EDI];
229                                                    data[typNo]  = selData[NO_TYP];
230    
231                                                    if( lenVal.contains( "," ) ) { data[lenNo] = lenVal ; }         // "," が含まれて?場合?、?設?
232                                            }
233                                    }
234                                    catch( RuntimeException ex ) {
235                                            ErrorMessage errMessage = makeErrorMessage( "TableFilter_CLMSET Error",ErrorMessage.NG );
236                                            errMessage.addMessage( row+1,ErrorMessage.NG,ex.getMessage() );
237                                            errMessage.addMessage( row+1,ErrorMessage.NG,StringUtil.array2csv( data ) );
238                                            errMessage.addMessage( row+1,ErrorMessage.NG,"CLM=[" + clmVal + "]" );
239                                    }
240                            }
241                    }
242    
243                    return table;
244            }
245    
246            /**
247             * RENDERER,EDITOR,DBTYPE の条件?を?マスター??タレコードから見つけて、対応するレコード?配?を返します??
248             *
249             * これは、?スタ??タは??番に評価して?、最初に成立した?をセ?します?
250             * マスタ??タは、clm,cls,len,biko につ?条件設定しておき、条件が?立するかど?判断hし?成立するレコードを
251             * 返すことで、そのレコードに該当する?RENDERER,EDITOR,DBTYPE の値を返します?
252             * これで、ある程度?な条件判定が可能になります?
253             * マスタ??タの null は、条件に含めな?無条件成立)を意味します?
254             *
255             * @og.rev 5.5.8.2 (2012/11/09) 新規追?
256             *
257             * @param  clmVal カラ?ータ(not null保障 , 大?保障)
258             * @param  clsVal  クラス??タ(not null保障 , 大?保障)
259             * @param  lenVal  長さデータ(not null , カンマ保障)
260             * @param  bikoVal 備???タ(not null保障)
261             * @return レコード?配?
262             */
263            private String[] serchMasterData( final String clmVal,final String clsVal,final String lenVal,final String bikoVal ) {
264                    String lenVal2  = ( lenVal.contains( "," ) ) ? "," : lenVal ;   // 少数を含??合??," を?そうでな??合?、そのまま返す?
265    
266                    int size = MASTER_DATA.length;
267                    for( int i=0; i<size; i++ ) {
268                            String[] rowData = MASTER_DATA[i];
269                            if( ( rowData[NO_CLM]  == null || clmVal.startsWith( rowData[NO_CLM] ) ) &&
270                                    ( rowData[NO_CLS]  == null || clsVal.startsWith( rowData[NO_CLS] ) ) &&
271                                    ( rowData[NO_LEN1] == null || rowData[NO_LEN1].equalsIgnoreCase( lenVal2 ) ) &&
272                                    ( rowData[NO_LEN2] == null || Integer.parseInt( lenVal ) >= Integer.parseInt( rowData[NO_LEN2] ) ) &&
273                                    ( rowData[NO_BIKO] == null || bikoVal.contains( rowData[NO_BIKO] ) ) ) {
274                                    return rowData ;
275                            }
276                    }
277    
278                    return MASTER_DATA[size-1] ;    // MASTER_DATA の?レコードでマッチする?で、来な???
279            }
280    
281            // 5.5.8.2 (2012/11/09) RENDERER,EDITOR,DBTYPE の条件?を変更します?
282            // 処??、上から?番に判定して?ます?で、ご注意く???
283            //* RENDERER,EDITOR,DBTYPE の条件?の マスター??タレコー?を設定します? {@value} */
284            private static final String[][] MASTER_DATA = new String[][] {
285            //   clm        , cls   , =len  , >=len      , biko  , renderer      , editor        , dbtype
286                    { "DY"  , null  , "4"   , null  , null  , "MD"          , "TEXT"        , "X"           } ,             // 日付文字?(時?)
287                    { "DY"  , null  , "6"   , null  , null  , "YM"          , "YM"          , "YM"          } ,             // 日付文字?(年日)
288                    { "DY"  , null  , "8"   , null  , null  , "YMD"         , "YMD"         , "YMD"         } ,             // 日付文字?(年月日)
289                    { "DY"  , null  , "14"  , null  , null  , "YMDH"        , "YMDH"        , "YMDH"        } ,             // 日付文字?(年月日時??
290                    { "TM"  , null  , "4"   , null  , null  , "HM"          , "TEXT"        , "HM"          } ,             // 時間??(時?)
291                    { "TM"  , null  , "6"   , null  , null  , "HMS"         , "TEXT"        , "HMS"         } ,             // 時間??(時??
292                    { "CD"  , null  , null  , null  , ":"   , "MENU"        , "MENU"        , "X"           } ,             // CODEリソース
293                    { "FG"  , null  , null  , null  , ":"   , "MENU"        , "MENU"        , "X"           } ,             // CODEリソース
294                    { "KB"  , null  , null  , null  , ":"   , "MENU"        , "MENU"        , "X"           } ,             // CODEリソース
295                    { null  , "NU"  , "1"   , null  , ":"   , "MENU"        , "MENU"        , "S9"          } ,             // NUMBER(整数)
296                    { null  , "IN"  , "1"   , null  , ":"   , "MENU"        , "MENU"        , "S9"          } ,             // INTEGER , INT64
297                    { null  , null  , "1"   , null  , ":"   , "MENU"        , "MENU"        , "X"           } ,             // CODEリソース
298                    { null  , "VA"  , null  , "30"  , null  , "LABEL"       , "TEXT"        , "KX"          } ,             // VARCHAR , VARCHAR2(30桁以上?漢?
299                    { null  , "VA"  , null  , null  , null  , "LABEL"       , "TEXT"        , "X"           } ,             // VARCHAR , VARCHAR2(30桁以下?英数?
300                    { null  , "NU"  , ","   , null  , null  , "NUMBER"      , "NUMBER"      , "R"           } ,             // NUMBER(少数)
301                    { null  , "NU"  , null  , null  , null  , "NUMBER"      , "NUMBER"      , "S9"          } ,             // NUMBER(整数)
302                    { null  , "IN"  , null  , null  , null  , "NUMBER"      , "NUMBER"      , "S9"          } ,             // INTEGER , INT64
303                    { null  , "DE"  , null  , null  , null  , "NUMBER"      , "NUMBER"      , "R"           } ,             // DECIMAL
304                    { null  , "TI"  , "8"   , null  , null  , "YMD"         , "YMD"         , "YMD"         } ,             // TIMESTAMP(8?
305                    { null  , "TI"  , "14"  , null  , null  , "YMDH"        , "YMDH"        , "YMDH"        } ,             // TIMESTAMP(14?
306                    { null  , "TI"  , null  , null  , null  , "DATE"        , "YMDH"        , "DATE"        } ,             // TIMESTAMP
307                    { null  , "DA"  , "8"   , null  , null  , "DATE"        , "YMD"         , "DATE"        } ,             // DATE(8?
308                    { null  , "DA"  , null  , null  , null  , "DATE"        , "YMDH"        , "DATE"        } ,             // DATE
309                    { null  , "CH"  , null  , null  , null  , "LABEL"       , "TEXT"        , "X"           } ,             // CHAR
310                    { null  , "CL"  , null  , null  , null  , "LABEL"       , "TEXT"        , "KX"          } ,             // CLOB
311                    { null  , null  , null  , null  , null  , "LABEL"       , "TEXT"        , "X"           }               // そ??
312            } ;
313    
314            private static final int NO_CLM  = 0;
315            private static final int NO_CLS  = 1;
316            private static final int NO_LEN1 = 2;
317            private static final int NO_LEN2 = 3;
318            private static final int NO_BIKO = 4;
319            private static final int NO_REN  = 5;
320            private static final int NO_EDI  = 6;
321            private static final int NO_TYP  = 7;
322    }