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}