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