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 java.io.File; 019import java.io.PrintWriter; 020import java.util.Map; 021 022import org.opengion.fukurou.util.ErrorMessage; 023import org.opengion.fukurou.util.FileUtil; 024import org.opengion.fukurou.util.FixLengthData; 025import org.opengion.fukurou.util.StringUtil; 026import org.opengion.hayabusa.common.HybsSystem; 027import org.opengion.hayabusa.common.HybsSystemException; 028import org.opengion.hayabusa.db.AbstractTableFilter; 029import org.opengion.hayabusa.db.DBTableModel; 030import org.opengion.hayabusa.resource.ResourceFactory; 031import org.opengion.hayabusa.resource.ResourceManager; 032 033/** 034 * TableFilter_DBARG_OUT は、TableFilter インターフェースを継承した、DBTableModel 処理用の 035 * 実装クラスです。 036 * 037 * ここでは、テーブル一覧の検索結果より、GF81 のARG変数チェックテーブルから 038 * 必要な情報を取得し、ARG変数作成スクリプトを作成します。 039 * 出力ファイルは、オブジェクト名+".sql" という命名規則で作成します。 040 * 検索では、(SYSTEM_ID,TBLSYU,OBJ_NAME,SEQNO,CLM,CLM_NAME,CLS_NAME,USE_LENGTH,MAX_LENGTH,TABLE_NAME) 041 * の項目を取得する必要があります。 042 * 043 * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか、BODY 部にCSS形式で記述します。 044 * 【パラメータ】 045 * { 046 * DIR : {@BASE_DIR}/sql/install/07_ARG ; 出力ファイルの基準フォルダ(必須) 047 * XML : false ; XML出力を行うかどうか[true/false]を指定します(初期値:false)。 048 * } 049 * 050 * @og.formSample 051 * ●形式: 052 * select SYSTEM_ID,TBLSYU,OBJ_NAME,SEQNO,CLM,CLM_NAME,CLS_NAME,USE_LENGTH,MAX_LENGTH,TABLE_NAME from GF81 053 * @ <og:tableFilter classId="DBARG_OUT" keys="DIR" vals="{@BASE_DIR}/sql/install/07_ARG" /> 054 * 055 * A <og:tableFilter classId="DBARG_OUT" > 056 * { 057 * DIR : {@BASE_DIR}/sql/install/07_ARG ; 058 * XML : false ; 059 * } 060 * </og:tableFilter> 061 * 062 * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを追加 063 * 064 * @version 0.9.0 2000/10/17 065 * @author Kazuhiko Hasegawa 066 * @since JDK1.1, 067 */ 068public class TableFilter_DBARG_OUT extends AbstractTableFilter { 069 //* このプログラムのVERSION文字列を設定します。 {@value} */ 070 private static final String VERSION = "5.6.7.0 (2013/07/27)" ; 071 072 /** 073 * keys の整合性チェックを行うための初期設定を行います。 074 * 075 * @og.rev 5.6.6.1 (2013/07/12) keys の整合性チェック対応 076 * 077 * @param keysMap keys の整合性チェックを行うための Map 078 */ 079 @Override 080 protected void init( final Map<String,String> keysMap ) { 081 keysMap.put( "DIR" , "出力ファイルの基準フォルダ(必須)" ); 082 keysMap.put( "XML" , "XML出力を行うかどうか[true/false]を指定(初期値:false)" ); // 5.6.7.0 (2013/07/27) xml対応 083 } 084 085 // 5.6.6.0 (2013/07/05) 検索項目を増やしておきます。 086 private static final String[] KEYS = new String[] { "SYSTEM_ID","TBLSYU","OBJ_NAME","SEQNO","CLM","CLM_NAME","CLS_NAME","USE_LENGTH","MAX_LENGTH","TABLE_NAME" }; 087 088 private static final int SYSTEM_ID = 0; 089 // private static final int TBLSYU = 1; 090 private static final int OBJ_NAME = 2; 091 private static final int SEQNO = 3; 092 private static final int CLM = 4; 093 private static final int CLM_NAME = 5; 094 private static final int CLS_NAME = 6; 095 private static final int USE_LENGTH = 7; 096 // private static final int MAX_LENGTH = 8; 097 // private static final int TABLE_NAME = 9; 098 099 // private static final String ENCODE = "Windows-31J" ; 100 private static final String ENCODE = "UTF-8" ; // 5.6.7.0 (2013/07/27) sqlも UTF-8 で出力 101 102 // 5.6.6.0 (2013/07/05) ヘッダー部作成用 103 private static final String CMNT = "************************************************************************" ; 104 105 private static final int X = FixLengthData.X ; // type 定数 106 private static final int S = FixLengthData.S ; // type 定数 107 private static final int K = FixLengthData.K ; // type 定数 108 private static final int T = FixLengthData.T ; // addLen 定数 109 private static final int T3= FixLengthData.T3 ; // addLen 定数 110 111 /** 5.6.7.0 (2013/07/27) 各種定数 */ 112 protected static final String XML_START_TAG = "<?xml version='1.0' encoding='UTF-8'?>" + CR + "<ROWSET tableName='xxx'>"; 113 protected static final String XML_END_TAG = "</ROWSET>"; 114 protected static final String EXEC_START_TAG= "<EXEC_SQL>"; 115 protected static final String EXEC_END_TAG = "</EXEC_SQL>"; 116 117 /** XML形式かどうか */ 118 protected boolean isXml = false; // 5.6.7.0 (2013/07/27) 119 120 private ResourceManager resource = null; // 5.6.6.0 (2013/07/05) ヘッダー用のリソース 121 122 /** 123 * DBTableModel処理を実行します。 124 * 125 * @og.rev 4.0.0.0 (2007/11/28) メソッドの戻り値をチェックします。 126 * @og.rev 5.5.2.6 (2012/05/25) protected変数を、private化したため、getterメソッドで取得するように変更 127 * @og.rev 5.6.7.0 (2013/07/27) xml 出力対応 128 * 129 * @return 処理結果のDBTableModel 130 */ 131 public DBTableModel execute() { 132 DBTableModel table = getDBTableModel(); // 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 133 134 isXml = StringUtil.nval( getValue( "XML" ), false ); // 5.6.7.0 (2013/07/27) xml 出力対応 135 136 int[] clmNo = getTableColumnNo( KEYS ); 137 138 File dir = new File( getValue( "DIR" ) ); 139 if( ! dir.exists() && !dir.mkdirs() ) { 140 String errMsg = "所定のフォルダが作成できませんでした。[" + dir + "]" ; 141 // 4.3.4.4 (2009/01/01) 142 throw new HybsSystemException( errMsg ); 143 } 144 145 // カンマ,カラム,クラス,(,桁数,),記号(--),表示順,名称 146 int[] addLen = new int[] { 0,T,0,0,0,T3,0,1,0 }; // 各データ間のスペース 147 int[] type = new int[] { X,X,X,X,S,X, X,S,K }; // 各データの種別 X:半角 S:空白前埋め K:全角混在 148 FixLengthData fixData = new FixLengthData( addLen,type ); 149 150 String[] data = null; 151 String oldObjName = null; 152 153 int rowCnt = table.getRowCount(); 154 for( int row=0; row<rowCnt; row++ ) { 155 String objName = null; 156 try { 157 data = table.getValues( row ); 158 objName = data[clmNo[OBJ_NAME]]; 159 160 // 5.6.6.0 (2013/07/05) 初めに一度だけ作成しておきます。 161 if( resource == null ) { 162 String systemId = data[clmNo[SYSTEM_ID]]; 163 resource = ResourceFactory.newInstance( systemId,"ja",false ); 164 } 165 166 boolean blk = ! objName.equals( oldObjName ) ; 167 if( row > 0 && blk ) { 168 // 5.6.7.0 (2013/07/27) xml 出力対応 169 PrintWriter writer = FileUtil.getPrintWriter( new File( dir,oldObjName + ( isXml ? ".xml" : ".sql" ) ),ENCODE ); 170 if( isXml ) { writer.println( XML_START_TAG ); } // 5.6.7.0 (2013/07/27) xml 出力対応 171 writer.print( makeHeadLine( oldObjName ) ); 172 writer.print( fixData.getAllFixData() ); 173 writer.println( makeEndLine( oldObjName ) ); 174 if( isXml ) { writer.println( XML_END_TAG ); } // 5.6.7.0 (2013/07/27) xml 出力対応 175 writer.close(); 176 fixData.clear(); 177 } 178 179 String[] outData = makeLineList( clmNo,data,blk ); 180 fixData.addListData( outData ); 181 182 oldObjName = objName ; 183 } 184 catch( RuntimeException ex ) { 185 ErrorMessage errMessage = makeErrorMessage( "TableFilter_DBARG_OUT Error",ErrorMessage.NG ); 186 errMessage.addMessage( row+1,ErrorMessage.NG,"ARG",ex.getMessage() ); 187 errMessage.addMessage( row+1,ErrorMessage.NG,"ARG",StringUtil.array2csv( data ) ); 188 errMessage.addMessage( row+1,ErrorMessage.NG,"ARG","OBJ_NAME=[" + objName + "]" ); 189 } 190 } 191 192 // 常に、一回り遅れてデータ出力している為、最後のデータを出力しておく必要がある。 193 // 5.6.7.0 (2013/07/27) xml 出力対応 194 PrintWriter writer = FileUtil.getPrintWriter( new File( dir,oldObjName + ( isXml ? ".xml" : ".sql" ) ),ENCODE ); 195 if( isXml ) { writer.println( XML_START_TAG ); } // 5.6.7.0 (2013/07/27) xml 出力対応 196 writer.print( makeHeadLine( oldObjName ) ); 197 writer.print( fixData.getAllFixData() ); 198 writer.println( makeEndLine( oldObjName ) ); 199 if( isXml ) { writer.println( XML_END_TAG ); } // 5.6.7.0 (2013/07/27) xml 出力対応 200 writer.close(); 201 fixData.clear(); 202 203 return table; 204 } 205 206 /** 207 * ヘッダーとして使用する文字列を作成します。 208 * 209 * @og.rev 5.6.6.0 (2013/07/05) ヘッダーとして各種情報をセットします。 210 * @og.rev 5.6.7.0 (2013/07/27) xml 出力対応 211 * 212 * @param objName オブジェクト名 213 * 214 * @return ヘッダーとして使用する文字列 215 */ 216 private String makeHeadLine( final String objName ) { 217 // objName から、ARG を取り除いた文字列が、画面IDになるはず。リソースから検索 218 String gamenId = objName.substring( 0,objName.length()-3 ); // 3文字は、"ARG" 分 219 String gamenNm = resource.getLabel( gamenId ) ; 220 221 String LINE1 = objName ; 222 String LINE2 = gamenId + " ( " + gamenNm + " )" ; 223 String LINE3 = "Created : " + HybsSystem.getDate() ; 224 225 int[] addLen = new int[] { 0,0,0 }; // 各データ間のスペース 226 int[] type = new int[] { X,K,X }; // 各データの種別 X:半角 S:空白前埋め K:全角混在 227 FixLengthData fixData = new FixLengthData( addLen,type ); 228 229 String[][] outData = new String[][] { 230 { "/**", CMNT , "**/" }, 231 { "/* ", LINE1, " */" }, 232 { "/* ", LINE2, " */" }, 233 { "/* ", LINE3, " */" }, 234 { "/**", CMNT , "**/" }, 235 }; 236 237 // 5.6.6.0 (2013/07/05) 簡易メソッドを利用 238 fixData.addAllListData( outData ); 239 240 StringBuilder buf = new StringBuilder(); 241 fixData.getAllFixData( buf ); 242 243 if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); } // 5.6.7.0 (2013/07/27) xml 出力対応 244 buf.append( "DROP TYPE " ).append( objName ).append( "_ARRAY" ); 245 if( isXml ) { buf.append( CR ).append( EXEC_END_TAG ).append( CR ); } // 5.6.7.0 (2013/07/27) xml 出力対応 246 else { buf.append( ";" ).append( CR ); } 247 248 if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); } // 5.6.7.0 (2013/07/27) xml 出力対応 249 buf.append( "CREATE OR REPLACE TYPE " ).append( objName ).append( " AS OBJECT" ).append( CR ); 250 buf.append( " (" ).append( CR ); 251 252 return buf.toString() ; 253 } 254 255 /** 256 * 各行に相当する文字列の配列を作成します。 257 * カンマ,カラム,クラス,(,桁数,),記号(--),表示順,名称 258 * 259 * @og.rev 5.5.1.9 (2012/04/18) useLen.length=0対応 260 * @og.rev 5.6.6.0 (2013/07/05) カラムの表示順も出力します。 261 * 262 * @param clmNo カラム番号配列 263 * @param data 1行分の入力データ配列 264 * @param first 最初の行かどうか[true:最初/false:それ以降] 265 * 266 * @return 1行分に相当する結果配列(カンマ,カラム,クラス(桁数),コメント記号,表示順,名称) 267 */ 268 private String[] makeLineList( final int[] clmNo,final String[] data,final boolean first ) { 269 // カンマ,カラム,クラス(桁数),記号(--),表示順,名称 270 String[] outData = new String[9]; // 5.6.6.0 (2013/07/05) カラムの表示順追加 271 272 outData[0] = first ? " " : " , " ; // 0:カンマ 273 outData[1] = data[clmNo[CLM]] ; // 1:カラム 274 275 String clsName = data[clmNo[CLS_NAME]]; 276 if( clsName.startsWith( "CLOB" ) || clsName.startsWith( "DATE" ) ) { 277 data[clmNo[USE_LENGTH]] = null; 278 } 279 String useLen = data[clmNo[USE_LENGTH]]; 280 if( useLen != null && ! useLen.equals( "0" ) && useLen.length() > 0 ) { // 5.5.1.9 (2012/04/19) 281 outData[2] = clsName ; // 2:クラス 282 outData[3] = " ( " ; // 3:( 283 outData[4] = useLen ; // 4:桁数 284 outData[5] = " )" ; // 5:) 285 } 286 else { 287 outData[2] = clsName ; // NUMBER型桁数オープン対応。ARGで使えるか不明。 288 } 289 290 String seqno = data[clmNo[SEQNO]] ; // 表示順 291 String nameJA = data[clmNo[CLM_NAME]] ; // 名称 292 if( nameJA != null ) { 293 outData[6] = "-- " ; // 3:コメント記号 294 outData[7] = seqno ; // 4:表示順 295 outData[8] = nameJA ; // 5:名称 296 } 297 298 return outData ; 299 } 300 301 /** 302 * 最後の行に相当する文字列を作成します。 303 * 304 * @og.rev 5.6.7.0 (2013/07/27) xml 出力対応 305 * 306 * @param objName オブジェクト名 307 * 308 * @return 最後の行に相当する文字列 309 */ 310 private String makeEndLine( final String objName ) { 311 312 StringBuilder buf = new StringBuilder(); 313 buf.append( " )" ); 314 315 if( isXml ) { buf.append( CR ).append( EXEC_END_TAG ).append( CR ); } // 5.6.7.0 (2013/07/27) xml 出力対応 316 else { buf.append( ";" ).append( CR ).append( "/" ).append( CR ); } 317 buf.append( CR ); 318 319 if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); } // 5.6.7.0 (2013/07/27) xml 出力対応 320 buf.append( "CREATE OR REPLACE TYPE " ).append( objName ).append( "_ARRAY" ); 321 buf.append( " AS VARRAY(1000) OF " ).append( objName ); 322 if( isXml ) { buf.append( CR ).append( EXEC_END_TAG ); } // 5.6.7.0 (2013/07/27) xml 出力対応 323 else { buf.append( ";" ).append( CR ).append( "/" ); } 324 325 return buf.toString() ; 326 } 327}