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.common.HybsSystemException; 019import org.opengion.hayabusa.db.AbstractTableFilter; 020import org.opengion.hayabusa.db.DBColumn; 021import org.opengion.hayabusa.db.DBTableModel; 022 023import org.opengion.hayabusa.resource.ResourceFactory; 024import org.opengion.hayabusa.resource.ResourceManager; 025 026import org.opengion.fukurou.util.ErrorMessage; 027import org.opengion.fukurou.util.StringUtil; 028import java.util.regex.Pattern; 029import java.util.regex.Matcher; 030import java.util.Locale; 031import java.util.Map; 032 033/** 034 * TableFilter_DBARG は、TableFilter インターフェースを継承した、DBTableModel 処理用の 035 * 実装クラスです。 036 * 037 * ここでは、テキストから、オブジェクト名、カラム名、クラス、利用桁数を切り出します。 038 * 039 * ソースのテキスト部は、",NAME_JA VARCHAR2(100) " という形式のテキストになっています。 040 * これを、カラム部、クラス名部、使用桁数部に分解します。上記の例では、 041 * それぞれを、NAME_JA、VARCHAR2、100 に分解して、文字列配列に格納します。 042 * また、これらのソースに、"--" や "/ * ・・・ * /" などのコメントが含まれるケースが 043 * あります。"--" コメントは、それ以降を無視しますが、"/ *" コメントは、複数行に 044 * またがる為、今回は処理対象から外します。 045 * ソースのテキスト部には、それら以外に、OBJECT_NAME に相当する行や、");" などの 046 * ソースの最初や最後の無効な部分があります。無効な部分は、null を返すことで 047 * 登録処理から省いてください。 048 * 049 * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか、BODY 部にCSS形式で記述します。 050 * 【パラメータ】 051 * { 052 * TEXT : 処理をおこなう、ソースのテキスト部のカラム名 053 * OBJ_NAME : キーとなるオブジェクト名のカラム名 054 * SEQNO : ソースの行番号のカラム名 055 * CLM : 処理結果のカラム名を格納するカラム名 056 * CLS_NAME : 処理結果のクラス名を格納するカラム名 057 * USE_LENGTH : 処理結果の利用桁数を格納するカラム名 058 * CLM_NAME : 処理結果のカラム名称(ラベル)を格納するカラム名 059 * MAX_LENGTH : 処理結果の桁数を格納するカラム名 060 * } 061 * 062 * @og.formSample 063 * ●形式: 064 * select A.OBJECT_NAME AS OBJ_NAME,B.LINE AS SEQNO,'' AS CLM , 065 * '' AS CLS_NAME,'' AS USE_LENGTH,'' AS CLM_NAME, 066 * '' AS TABLE_NAME ,'' AS MAX_LENGTH, 067 * B.TEXT , '{@SYSTEM_ID}' AS SYSTEM_ID,'{@TBLSYU}' AS TBLSYU 068 * from USER_OBJECTS A inner join USER_SOURCE B 069 * on A.OBJECT_NAME = B.NAME 070 * where A.OBJECT_TYPE = 'TYPE' 071 * and B.TYPE = 'TYPE' 072 * and not A.OBJECT_NAME like '%ARRAY' 073 * order by A.OBJECT_NAME,B.LINE 074 * ① <og:tableFilter classId="DBARG" 075 * keys="TEXT,OBJ_NAME,SEQNO,CLM,CLS_NAME,USE_LENGTH,CLM_NAME,MAX_LENGTH" 076 * vals="TEXT,OBJ_NAME,SEQNO,CLM,CLS_NAME,USE_LENGTH,CLM_NAME,MAX_LENGTH" /> 077 * 078 * ② <og:tableFilter classId="DBARG" > 079 * { 080 * TEXT : 処理をおこなう、ソースのテキスト部のカラム名 081 * OBJ_NAME : キーとなるオブジェクト名のカラム名 082 * SEQNO : ソースの行番号のカラム名 083 * CLM : 処理結果のカラム名を格納するカラム名 084 * CLS_NAME : 処理結果のクラス名を格納するカラム名 085 * USE_LENGTH : 処理結果の利用桁数を格納するカラム名 086 * CLM_NAME : 処理結果のカラム名称(ラベル)を格納するカラム名 087 * MAX_LENGTH : 処理結果の桁数を格納するカラム名 088 * } 089 * </og:tableFilter> 090 * 091 * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを追加 092 * 093 * @version 0.9.0 2000/10/17 094 * @author Kazuhiko Hasegawa 095 * @since JDK1.1, 096 */ 097public class TableFilter_DBARG extends AbstractTableFilter { 098 //* このプログラムのVERSION文字列を設定します。 {@value} */ 099 private static final String VERSION = "5.6.6.1 (2013/07/12)" ; 100 101 private static final Pattern pt = Pattern.compile( "[^\\w]*([\\w]*)[^\\w]*(VARCHAR2|NUMBER)[\\s]*([\\(\\d,\\)]*)",Pattern.CASE_INSENSITIVE ); 102 // (______) (_______________) (_____________) 103 104 /** 105 * keys の整合性チェックを行うための初期設定を行います。 106 * 107 * @og.rev 5.6.6.1 (2013/07/12) keys の整合性チェック対応 108 * 109 * @param keysMap keys の整合性チェックを行うための Map 110 */ 111 @Override 112 protected void init( final Map<String,String> keysMap ) { 113 keysMap.put( "TEXT" , "処理をおこなう、ソースのテキスト部のカラム名" ); 114 keysMap.put( "OBJ_NAME" , "キーとなるオブジェクト名のカラム名" ); 115 keysMap.put( "SEQNO" , "ソースの行番号のカラム名" ); 116 keysMap.put( "CLM" , "処理結果のカラム名を格納するカラム名" ); 117 keysMap.put( "CLS_NAME" , "処理結果のクラス名を格納するカラム名" ); 118 keysMap.put( "USE_LENGTH" , "処理結果の利用桁数を格納するカラム名" ); 119 keysMap.put( "CLM_NAME" , "処理結果のカラム名称(ラベル)を格納するカラム名" ); 120 keysMap.put( "MAX_LENGTH" , "処理結果の桁数を格納するカラム名" ); 121 } 122 123 // 5.5.7.4 (2012/10/25) OBJ_NAME,SEQNO 追加 124 private static final String[] KEYS = new String[] { "TEXT","OBJ_NAME","SEQNO","CLM","CLS_NAME","USE_LENGTH","CLM_NAME","MAX_LENGTH" }; 125 private static final int TEXT = 0; 126 private static final int OBJ_NAME = 1; // 5.5.7.4 (2012/10/25) OBJ_NAME 追加 127 private static final int SEQNO = 2; // 5.5.7.4 (2012/10/25) SEQNO 追加 128 private static final int CLM = 3; 129 private static final int CLS_NAME = 4; 130 private static final int USE_LENGTH = 5; 131 private static final int CLM_NAME = 6; 132 private static final int MAX_LENGTH = 7; 133 134 /** 135 * DBTableModel処理を実行します。 136 * 137 * @og.rev 5.5.2.6 (2012/05/25) protected変数を、private化したため、getterメソッドで取得するように変更 138 * @og.rev 5.5.7.4 (2012/10/25) OBJ_NAME,SEQNO を追加することで、SEQNO を振りなおします。 139 * 140 * @return 処理結果のDBTableModel 141 */ 142 public DBTableModel execute() { 143 DBTableModel table = getDBTableModel(); // 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 144 145 String lang = getValue( "LANG" ); 146 ResourceManager resource = ResourceFactory.newInstance( lang ); 147 148 int size = KEYS.length; 149 int[] clmNo = new int[size]; 150 for( int i=0; i<size; i++ ) { 151 String clm = getValue( KEYS[i] ); 152 clmNo[i] = table.getColumnNo( clm,false ); // 存在しない場合は、-1 153 if( clmNo[i] < 0 ) { 154 String errMsg = "検索結果に、[" + clm + "]を含めてください。" ; 155 throw new HybsSystemException( errMsg ); 156 } 157 } 158 159 String[] data = null; 160 int rowCnt = table.getRowCount(); 161 DBTableModel rtnTbl = table.newModel(); 162 String bkObjName = ""; // 5.5.7.4 (2012/10/25) SEQNO を振りなおすためのキーブレイク 163 int seqno = 1 ; // 5.5.7.4 (2012/10/25) SEQNO 164 for( int row=0; row<rowCnt; row++ ) { 165 try { 166 data = table.getValues( row ); 167 String text = data[clmNo[TEXT]] ; 168 String[] temp = textSeparate( text ); 169 if( temp != null ) { 170 String objName = data[clmNo[OBJ_NAME]]; // 5.5.7.4 (2012/10/25) SEQNO を振りなおす 171 if( ! bkObjName.equals( objName ) ) { 172 bkObjName = objName; 173 seqno = 1; 174 } 175 176 data[clmNo[SEQNO]] = String.valueOf( seqno++ ); // 5.5.7.4 (2012/10/25) SEQNO を振りなおす 177 data[clmNo[CLM]] = temp[0]; 178 data[clmNo[CLS_NAME]] = temp[1]; 179 data[clmNo[USE_LENGTH]] = temp[2]; 180 // data[clmNo[CLM_NAME]] = resource.getLabel( temp[0] ) ; 181 182 DBColumn dbClm = resource.getDBColumn( temp[0] ); 183 if( dbClm != null ) { 184 data[clmNo[CLM_NAME]] = dbClm.getLabel() ; 185 String len = data[clmNo[MAX_LENGTH]] ; 186 if( len == null || len.length() == 0 ) { 187 data[clmNo[MAX_LENGTH]] = dbClm.getMaxlength() ; 188 } 189 } 190 // else { 191 // data[clmNo[CLM_NAME]] = temp[0] ; // ラベルが存在しない 192 // } 193 rtnTbl.addColumnValues( data ); 194 } 195 } 196 catch( RuntimeException ex ) { 197 ErrorMessage errMessage = makeErrorMessage( "TableFilter_DBARG Error",ErrorMessage.NG ); 198 errMessage.addMessage( row+1,ErrorMessage.NG,"ERR MSG",ex.getMessage() ); 199 errMessage.addMessage( row+1,ErrorMessage.NG,"ERR Data",StringUtil.array2csv( data ) ); 200 } 201 } 202 203 return rtnTbl; 204 } 205 206 /** 207 * ソースのテキスト部を分割します。 208 * 209 * ソースのテキスト部は、",NAME_JA VARCHAR2(100) " という形式のテキストになっています。 210 * これを、カラム部、クラス名部、使用桁数部に分解します。上記の例では、 211 * それぞれを、NAME_JA、VARCHAR2、100 に分解して、文字列配列に格納します。 212 * また、これらのソースに、"--" や "/ * ・・・ * /" などのコメントが含まれるケースが 213 * あります。"--" コメントは、それ以降を無視しますが、"/ *" コメントは、複数行に 214 * またがる為、今回は処理対象から外します。 215 * ソースのテキスト部には、それら以外に、OBJECT_NAME に相当する行や、");" などの 216 * ソースの最初や最後の無効な部分があります。無効な部分は、null を返すことで 217 * 登録処理から省いてください。 218 * 219 * @og.rev 5.5.7.4 (2012/10/25) カラムの大文字化と、桁数の 前0 削除 220 * @og.rev 5.5.8.5 (2012/11/27) 桁数なしの場合の対応 221 * 222 * @param text ソースのテキスト部 223 * 224 * @return 分割後の文字列配列(CLM,CLS_NAME,USE_LENGTHの順)、無効なデータは null 225 */ 226 private String[] textSeparate( final String text ) { 227 228 int adrs = text.indexOf( "--" ); 229 String text2 = (adrs<0) ? text : text.substring( 0,adrs ) ; 230 231 String[] rtnTxt = null ; 232 Matcher mt = pt.matcher( text2 ); 233 if( mt.lookingAt() ) { 234 String clm = mt.group( 1 ); // カラムの名称:パターンとして、空白は含まない 235 String cls = mt.group( 2 ); // クラスの名称(VARCHAR2|NUMBER) 236 String len = mt.group( 3 ); // 桁数:パターンとして、前後に空白を含む、()を含む、何もないなど 237 238 // 5.5.8.5 (2012/11/27) 桁数なしの場合の対応 239 if( len != null ) { 240 int st = len.indexOf( '(' ); 241 int ed = len.indexOf( ')' ); 242 if( st >= 0 && ed >= 0 ) { 243 len = len.substring( st+1,ed ); 244 len = len.trim().replaceFirst("^0+", ""); // 5.5.7.4 (2012/10/25) 先頭の 0 を削除する。 245 } 246 else { 247 len = ""; 248 } 249 } 250 else { 251 len = ""; 252 } 253 254 if( clm != null && cls != null ) { 255 clm = clm.toUpperCase(Locale.JAPAN); // 5.5.7.4 (2012/10/25) 大文字化 256 cls = cls.toUpperCase(Locale.JAPAN); // 5.5.7.4 (2012/10/25) 大文字化 257 rtnTxt = new String[] { clm,cls,len }; 258 } 259 } 260 261 // マッチしない または 条件を満たさない場合は、null 262 return rtnTxt ; 263 } 264}