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 org.opengion.hayabusa.db.AbstractTableFilter;
019import org.opengion.hayabusa.db.DBTableModel;
020
021import org.opengion.fukurou.util.ErrorMessage;
022import org.opengion.fukurou.util.StringUtil;
023
024import java.util.Locale;
025import java.util.Map;
026
027/**
028 * TableFilter_DTYPE は、TableFilter インターフェースを継承した、DBTableModel 処理用の
029 * 実装クラスです。
030 *
031 * ここでは、キーの CLS_NAME,USE_LENGTH より、DTYPE の値を設定します。
032 *  CLS_NAME は、VARCHAR2, NUMBER などのカラムの属性を表します。
033 *  USE_LENGTH は、長さ(使用桁数)です。
034 *  DTYPE は、X(10) や、 S9(8) などの簡易型カラム属性です。
035 * エンジンを使用したシステムでは、この属性より、さらに詳細にカラムを定義する、
036 * DBTYPE 属性が、あります。将来的には、この定義を使用するように切り替えていく予定です。
037 *
038 * CLS_NAME,USE_LENGTH,DTYPE の カラム名については、初期値はこのままですが、
039 * keys , vals に指定すれば、別名についても使用することが可能です。
040 *
041 * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか、BODY 部にCSS形式で記述します。
042 * 【パラメータ】
043 *  {
044 *       CLS_NAME   : CLS_NAME   ;    VARCHAR2, NUMBER などのカラム属性を指定するカラム名を指定します。(初期値:CLS_NAME)
045 *       USE_LENGTH : USE_LENGTH ;    長さ(使用桁数)を表すカラム名を指定します。                 (初期値:USE_LENGTH)
046 *       DTYPE      : DTYPE      ;    X,R,S9,R,D,CLOB など、エンジンを使用したシステムで規定した詳細定義(初期値:DTYPE)
047 *  }
048 *
049 * @og.formSample
050 * ●形式:
051 *      @ <og:tableFilter classId="DTYPE" keys="CLS_NAME,USE_LENGTH,DTYPE" vals='"TABLE_NAME,CLM"' />
052 *
053 *      A <og:tableFilter classId="DTYPE" >
054 *               {
055 *                   CLS_NAME   : CLS_NAME   ;
056 *                   USE_LENGTH : USE_LENGTH ;
057 *                   DTYPE      : DTYPE      ;
058 *               }
059 *         </og:tableFilter>
060 *
061 * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを追加
062 *
063 * @version  0.9.0  2000/10/17
064 * @author   Kazuhiko Hasegawa
065 * @since    JDK1.5,
066 */
067public class TableFilter_DTYPE extends AbstractTableFilter {
068        //* このプログラムのVERSION文字列を設定します。   {@value} */
069        private static final String VERSION = "5.6.6.1 (2013/07/12)" ;
070
071        /**
072         * keys の整合性チェックを行うための初期設定を行います。
073         *
074         * @og.rev 5.6.6.1 (2013/07/12) keys の整合性チェック対応
075         *
076         * @param       keysMap keys の整合性チェックを行うための Map
077         */
078        @Override
079        protected void init( final Map<String,String> keysMap ) {
080                keysMap.put( "CLS_NAME"         , "VARCHAR2, NUMBER などのカラム属性を指定するカラム名を指定(初期値:CLS_NAME)"                                         );
081                keysMap.put( "USE_LENGTH"       , "長さ(使用桁数)を表すカラム名を指定 (初期値:USE_LENGTH)" );
082                keysMap.put( "DTYPE"            , "X,R,S9,R,D,CLOB など、エンジンを使用したシステムで規定した詳細定義(初期値:DTYPE)"        );
083        }
084
085        /**
086         * DBTableModel処理を実行します。
087         *
088         * @og.rev 5.5.2.6 (2012/05/25) protected変数を、private化したため、getterメソッドで取得するように変更
089         * @og.rev 5.5.8.2 (2012/11/09) X,S9 の条件分けを変更します。(MICS対応)
090         *
091         * @return 処理結果のDBTableModel
092         */
093        public DBTableModel execute() {
094                DBTableModel table = getDBTableModel();         // 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加
095
096                String cls = StringUtil.nval( getValue( "CLS_NAME" )    ,"CLS_NAME" );
097                String len = StringUtil.nval( getValue( "USE_LENGTH" )  ,"USE_LENGTH" );
098                String typ = StringUtil.nval( getValue( "DTYPE" )               ,"DTYPE" );
099
100                int clsNo  = table.getColumnNo( cls,false );    // 存在しない場合は、-1 を返す。
101                int lenNo  = table.getColumnNo( len,false );
102                int typNo  = table.getColumnNo( typ,false );
103
104                if( clsNo >= 0 && lenNo >= 0 && typNo >= 0 ) {
105                        String[] data  = null;
106                        int rowCnt = table.getRowCount();
107                        String clsVal = null;
108                        String lenVal = null;
109                        for( int row=0; row<rowCnt; row++ ) {
110                                try {
111                                        data   = table.getValues( row );
112                                        clsVal = ( data[clsNo] == null ) ? "" : data[clsNo].trim().toUpperCase(Locale.JAPAN) ;  // CLS_NAME(VARCHAR,NUMBER など)
113                                        lenVal = ( data[lenNo] == null ) ? "" : data[lenNo].trim().replace( '.',',' ) ;                 // USE_LENGTH(使用桁数)
114
115                                        // 長さで、小数部が、 0 の場合は、整数のみと判断する。
116                                        int cm = lenVal.indexOf( ",0" );
117                                        if( cm >= 0 ) { lenVal = lenVal.substring( 0,cm ); }
118
119                                        // 5.5.8.2 (2012/11/09) X,S9 の条件分けを変更します。(MICS対応)
120                                        String typVal = makeDTYPE( clsVal ,lenVal ) ;
121                                        data[typNo] = typVal;
122
123                                        if( lenVal.contains( "," ) ) { data[lenNo] = lenVal ; }         // "," が含まれている場合は、、再設定
124
125        //                              table.setValueAt( typVal,row,typNo );
126
127//                                      StringBuilder typVal = new StringBuilder();
128//                                      // 5.5.8.2 (2012/11/09) X,S9 の条件分けを変更します。
129//                                      String clsVal2 = clsVal.substring(0,2);                                         // 先頭2文字で判定します。
130//                                      // NUMBER , INTEGER , INT64 , DECIMAL
131//                                      if( "NU".equalsIgnoreCase( clsVal2 ) || "IN".equalsIgnoreCase( clsVal2 ) || "DE".equalsIgnoreCase( clsVal2 ) ) {
132//                                              typVal.append( "S9(" );
133//                                      }
134//                                      // TIMESTAMP , DATE
135//                                      else if( "TI".equalsIgnoreCase( clsVal2 ) || "DA".equalsIgnoreCase( clsVal2 ) ) {
136//                                              typVal.append( "T(" );
137//                                      }
138//                                      // VARCHAR , VARCHAR2 , CHAR , CLOB
139//                      //              else if( "VA".equalsIgnoreCase( clsVal2 ) || "CH".equalsIgnoreCase( clsVal2 ) || "CL".equalsIgnoreCase( clsVal2 ) ) {
140//                      //                      typVal.append( "X(" );
141//                      //              }
142//                                      else {
143//                                              typVal.append( "X(" );
144//                                      }
145//
146////                                    if( "NUMBER".equalsIgnoreCase( clsVal ) ) {
147////                                            typVal.append( "S9(" );
148////                                    }
149////                                    else {
150////                                            typVal.append( "X(" );
151////                                    }
152//
153//                                      int cm = lenVal.indexOf( ".0" );
154//                                      if( cm > 0 ) {
155//                                              typVal.append( lenVal.substring( 0,cm ) );
156//                                      }
157//                                      else {
158//                                              typVal.append( lenVal );
159//                                      }
160//                                      typVal.append( ')' );
161//
162//                                      table.setValueAt( typVal.toString(),row,typNo );
163                                }
164                                catch( RuntimeException ex ) {
165                                        ErrorMessage errMessage = makeErrorMessage( "TableFilter_DTYPE Error",ErrorMessage.NG );
166                                        errMessage.addMessage( row+1,ErrorMessage.NG,ex.getMessage() );
167                                        errMessage.addMessage( row+1,ErrorMessage.NG,StringUtil.array2csv( data ) );
168                                        errMessage.addMessage( row+1,ErrorMessage.NG,"CLS=[" + clsVal + "],LEN=[" + lenVal + "]" );
169                                }
170                        }
171                }
172
173                return table;
174        }
175
176        /**
177         * クラス,長さデータ から、DTYPE 文字列を作成します。
178         *
179         * if文の羅列から、マスタデータを利用した条件判定方式で判定します。
180         * また、以前からの、S9:数字 と、 X:文字 だけではなく、R:少数、D:日時、CLOB:テキスト を追加します。
181         * 桁数未設定の場合は、(桁数) を使用せず、記号だけになります。
182         *
183         * @og.rev 5.5.8.2 (2012/11/09) 新規追加
184         *
185         * @param  clsVal クラスデータ(not null保障 , 大文字保障)
186         * @param  lenVal 長さデータ(not null , カンマ保障)
187         * @return 対応する DTYPE 文字列
188         */
189        private String makeDTYPE( final String clsVal,final String lenVal ) {
190                StringBuilder typVal = new StringBuilder();
191
192                int size = MASTER_DATA.length;
193                for( int i=0; i<size; i++ ) {
194                        String clsMstr = MASTER_DATA[i][NO_CLS];
195                        String lenMstr = MASTER_DATA[i][NO_LEN];
196
197                        if( ( clsMstr  == null || clsVal.startsWith( clsMstr ) ) &&
198                                ( lenMstr  == null || lenVal.contains(   lenMstr ) ) ) {
199                                typVal.append( MASTER_DATA[i][NO_TYP] );
200                                break ;
201                        }
202                }
203                if( typVal.length() == 0 ) { typVal.append( MASTER_DATA[size-1][NO_TYP] ); }            // MASTER_DATA の最終レコードでマッチするので、来ないはず
204
205                if( ! lenVal.isEmpty() ) {              // 長さが存在する場合は、(xx)の数字部分を記述する。これが通常のケース
206                        typVal.append( "(" ).append( lenVal ).append( ")" );
207                }
208
209                return typVal.toString();
210        }
211
212        // 5.5.8.2 (2012/11/09) DTYPE の条件分けを変更します。
213        //* DTYPE の条件分けの マスターデータレコード を設定します。    {@value} */
214        private static final String[][] MASTER_DATA = new String[][] {
215        //    cls       , len   , dbtype
216                { "VA"  , null  , "X"           } ,             // VARCHAR , VARCHAR2
217                { "NU"  , ","   , "R"           } ,             // NUMBER(少数)
218                { "NU"  , null  , "S9"          } ,             // NUMBER(整数)
219                { "IN"  , null  , "S9"          } ,             // INTEGER , INT64
220                { "DE"  , null  , "R"           } ,             // DECIMAL
221                { "TI"  , null  , "D"           } ,             // TIMESTAMP
222                { "DA"  , null  , "D"           } ,             // DATE
223                { "CL"  , null  , "CLOB"        } ,             // CLOB
224                { null  , null  , "X"           }               // その他(CHAR , LONG 他)
225        } ;
226
227        private static final int NO_CLS  = 0;
228        private static final int NO_LEN  = 1;
229        private static final int NO_TYP  = 2;
230}