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 */
016 package org.opengion.plugin.table;
017
018 import java.io.File;
019 import java.io.PrintWriter;
020 import java.util.Locale;
021 import java.util.Map;
022
023 import org.opengion.fukurou.db.DBUtil;
024 import org.opengion.fukurou.db.Transaction; // 5.5.2.6 (2012/05/25)
025 import org.opengion.fukurou.util.ErrorMessage;
026 import org.opengion.fukurou.util.FileUtil;
027 import org.opengion.fukurou.util.FixLengthData;
028 import org.opengion.fukurou.util.StringUtil;
029 import org.opengion.hayabusa.common.HybsSystem;
030 import org.opengion.hayabusa.common.HybsSystemException;
031 import org.opengion.hayabusa.db.AbstractTableFilter;
032 import org.opengion.hayabusa.db.DBTableModel;
033
034 /**
035 * TableFilter_TABLE は、TableFilter インターフェースを継承した、DBTableModel 処?の
036 * 実?ラスです?
037 *
038 * ここでは、テーブル?の検索結果より、GF05 の??ブルカラ?義??ブルから
039 * ?な??を取得し、テーブル作?スクリプトを作?します?
040 * 出力ファイルは、テーブル名?S.sql" と?命名規則で作?します?
041 * 検索では?SYSTEM_ID,TBLSYU,TABLE_NAME,NAME_JA,TABLESPACE_NAME,INITIAL_EXTENT,NEXT_EXTENT,COMMENTS)
042 * の?を取得する?があります?
043 *
044 * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか?BODY 部にCSS形式で記述します?
045 * 【パラメータ?
046 * {
047 * DIR : {@BASE_DIR}/sql/01_TABLE ; 出力ファイルの基準フォル???)
048 * XML : false ; XML出力を行うかど?[true/false]を指定しま?初期値:false)?
049 * }
050 *
051 * @og.formSample
052 * ●形式?
053 * select SYSTEM_ID,TBLSYU,TABLE_NAME,NAME_JA,TABLESPACE_NAME,INITIAL_EXTENT,NEXT_EXTENT,COMMENTS from GF05
054 *
055 * ?<og:tableFilter classId="TABLE" keys="DIR,XML" vals='"{@BASE_DIR}/sql/01_TABLE,"' />
056 *
057 * ② <og:tableFilter classId="TABLE" >
058 * {
059 * DIR : {@BASE_DIR}/sql/01_TABLE ;
060 * XML : false ;
061 * }
062 * </og:tableFilter>
063 *
064 * @og.rev 4.0.0.0 (2005/08/31) 新規作?
065 * @og.rev 5.6.6.0 (2013/07/05) keys の整合?チェ?を追?
066 *
067 * @version 0.9.0 2000/10/17
068 * @author Kazuhiko Hasegawa
069 * @since JDK1.1,
070 */
071 public class TableFilter_TABLE extends AbstractTableFilter {
072 //* こ?プログラ??VERSION??を設定します? {@value} */
073 private static final String VERSION = "5.6.6.2 (2013/07/19)" ;
074
075 /**
076 * keys の整合?チェ?を行うための初期設定を行います?
077 *
078 * @og.rev 5.6.6.1 (2013/07/12) keys の整合?チェ?対?
079 *
080 * @param keysMap keys の整合?チェ?を行うための Map
081 */
082 @Override
083 protected void init( final Map<String,String> keysMap ) {
084 keysMap.put( "DIR" , "出力ファイルの基準フォル???)" );
085 keysMap.put( "XML" , "XML出力を行うかど?[true/false]を指?初期値:false)" );
086 }
087
088 private static final String[] DBKEY = {"SYSTEM_ID","TBLSYU","TABLE_NAME","NAME_JA",
089 "TABLESPACE_NAME","INITIAL_EXTENT","NEXT_EXTENT","COMMENTS" };
090
091 // 5.1.1.0 (2009/12/01) ??タのアクセス用の配?番号のID?private ?protected にします?
092 /** ??タのアクセス用の配?番号 {@value} */
093 protected static final int SYSTEM_ID = 0;
094 /** ??タのアクセス用の配?番号 {@value} */
095 protected static final int TBLSYU = 1;
096 /** ??タのアクセス用の配?番号 {@value} */
097 protected static final int TABLE_NAME = 2;
098 /** ??タのアクセス用の配?番号 {@value} */
099 protected static final int NAME_JA = 3;
100 /** ??タのアクセス用の配?番号 {@value} */
101 protected static final int TABLESPACE_NAME = 4;
102 /** ??タのアクセス用の配?番号 {@value} */
103 protected static final int INITIAL_EXTENT = 5;
104 /** ??タのアクセス用の配?番号 {@value} */
105 protected static final int NEXT_EXTENT = 6;
106 /** ??タのアクセス用の配?番号 {@value} */
107 protected static final int COMMENTS = 7;
108
109 private static final String GF05_SEL = "SELECT CLM,SEQNO,NAME_JA,CLS_NAME,USE_LENGTH,DATA_DEFAULT,NOT_NULL,'' AS OPTS"
110 + " FROM GF05"
111 + " WHERE SYSTEM_ID=? AND TBLSYU=? AND TABLE_NAME=?"
112 + " AND FGJ='1'"
113 + " ORDER BY SEQNO" ;
114
115 /** ??タのアクセス用の配?番号 {@value} */
116 protected static final int GF05_CLM = 0;
117 /** ??タのアクセス用の配?番号 {@value} */
118 protected static final int GF05_SEQNO = 1;
119 /** ??タのアクセス用の配?番号 {@value} */
120 protected static final int GF05_NAME_JA = 2;
121 /** ??タのアクセス用の配?番号 {@value} */
122 protected static final int GF05_CLS_NAME = 3;
123 /** ??タのアクセス用の配?番号 {@value} */
124 protected static final int GF05_USE_LENGTH = 4;
125 /** ??タのアクセス用の配?番号 {@value} */
126 protected static final int GF05_DATA_DEFAULT= 5;
127 /** ??タのアクセス用の配?番号 {@value} */
128 protected static final int GF05_NOT_NULL = 6;
129 /** ??タのアクセス用の配?番号 {@value} */
130 protected static final int GF05_OPTIONS = 7;
131
132 // private static final String ENCODE = "Windows-31J" ;
133 private static final String ENCODE = "UTF-8" ; // 4.3.6.6 (2009/05/15)
134 // private static final String CR = HybsSystem.CR ; // 5.1.1.0 (2009/12/01) CR 定義をAbstractTableFilterで行う?
135
136 private static final String CMNT = "************************************************************************" ;
137
138 private static final int X = FixLengthData.X ; // type 定数
139 private static final int S = FixLengthData.S ; // type 定数
140 private static final int K = FixLengthData.K ; // type 定数
141 private static final int T = FixLengthData.T ; // addLen 定数
142 private static final int T2= FixLengthData.T2 ; // addLen 定数
143
144 /** ?定数 */
145 protected static final String XML_START_TAG = "<?xml version='1.0' encoding='UTF-8'?>" + CR + "<ROWSET tableName='xxx'>";
146 protected static final String XML_END_TAG = "</ROWSET>";
147 protected static final String EXEC_START_TAG= "<EXEC_SQL>";
148 protected static final String EXEC_END_TAG = "</EXEC_SQL>";
149
150 /** XML形式かど? */
151 protected boolean isXml = false; // 4.3.7.0 (2009/06/01)
152
153 /**
154 * DBTableModel処?実行します?
155 *
156 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設?
157 * @og.rev 4.0.0.0 (2007/11/28) メソ?の戻り?をチェ?します?
158 * @og.rev 4.3.7.0 (2009/06/01) トリガー、SEQUENCE作?機?、XML出力機?追?
159 * @og.rev 5.1.1.0 (2009/12/01) XML_START_TAG に、tableName をセ?します?
160 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対?
161 * @og.rev 5.5.2.6 (2012/05/25) protected変数を?private化したため?getterメソ?で取得するよ?変更
162 * @og.rev 5.6.6.0 (2013/07/05) FixLengthData の簡易コンストラクタを使用
163 *
164 * @return 実行結果の??ブルモ?
165 */
166 public DBTableModel execute() {
167 DBTableModel table = getDBTableModel(); // 5.5.2.6 (2012/05/25) インターフェースにgetterメソ?追?
168
169 isXml = StringUtil.nval( getValue( "XML" ), false );
170
171 int[] clmNo = getTableColumnNo( DBKEY );
172 int rowCnt = table.getRowCount();
173
174 File dir = new File( getValue( "DIR" ) );
175 if( ! dir.exists() && ! dir.mkdirs() ) {
176 String errMsg = "??フォル?作?できませんでした?" + dir + "]" ;
177 // 4.3.4.4 (2009/01/01)
178 throw new HybsSystemException( errMsg );
179 }
180
181 // カン?カラ?クラス,(,桁数,),初期値,NOT_NULL,拡張機?,コメント開?行番号,名称,コメント終?
182 // 5.6.6.0 (2013/07/05) FixLengthData の簡易コンストラクタを使用
183 // FixLengthData fixData = new FixLengthData(10);
184
185 // カン?カラ?クラス,(,桁数,),初期値,NOT_NULL,拡張機?,コメント開?行番号,名称,コメント終?
186 int[] addLen = new int[] { 0,T,0,0,0,T2,T,T,T2,0,1,T,0 }; // ?ータ間?スペ?ス
187 int[] type = new int[] { X,X,X,X,S,X, X,X,X, X,S,K,X }; // ?ータの種別 X:半?S:空白前埋?K:全角混在
188 // fixData.setAddLength( addLen );
189 // fixData.setType( type );
190 FixLengthData fixData = new FixLengthData( addLen,type );
191
192 String[] data = null;
193 Transaction tran = getTransaction(); // 5.5.2.6 (2012/05/25)
194 for( int row=0; row<rowCnt; row++ ) {
195 String tableName = null;
196 try {
197 data = table.getValues( row );
198 String systemId = data[clmNo[SYSTEM_ID]];
199 String tblsyu = data[clmNo[TBLSYU]];
200 tableName = data[clmNo[TABLE_NAME]];
201
202 PrintWriter writer = FileUtil.getPrintWriter( new File( dir,tableName + ( isXml ? "S.xml" : "S.sql" ) ),ENCODE );
203
204 if( isXml ) { writer.println( XML_START_TAG.replace( "xxx",tableName ) ); } // 5.1.1.0 (2009/12/01) tableName をセ?
205 writer.print( makeHeadLine( clmNo,data ) );
206
207 String[] vals = new String[] { systemId,tblsyu,tableName };
208 // String[][] gf05 = DBUtil.dbExecute( GF05_SEL,vals,appInfo );
209 String[][] gf05 = DBUtil.dbExecute( GF05_SEL,vals,tran ); // 5.1.9.0 (2010/08/01) Transaction 対?
210
211 String uniqName = null;
212 fixData.clear();
213 // 値セ??まず?、最大長を求める?がある?
214 for( int i=0; i<gf05.length; i++ ) {
215 String[] outData = makeLineList( gf05[i],i==0 );
216 fixData.addListData( outData );
217
218 // 4.3.7.0 (2009/06/01)
219 if( "UNIQ".equalsIgnoreCase( gf05[i][GF05_CLM] ) || "UNIQSEQ".equalsIgnoreCase( gf05[i][GF05_CLM] ) ) {
220 uniqName = gf05[i][GF05_CLM].toUpperCase( Locale.JAPAN );
221 }
222 }
223 // 固定長化:最大長であわせた??を?力します?
224 for( int i=0; i<gf05.length; i++ ) {
225 writer.println( fixData.getFixData( i ) );
226 }
227 writer.println( makeEndLine( clmNo,data ) );
228
229 // 4.3.7.0 (2009/06/01) UNIQ?のSEQとトリガーを作?
230 if( uniqName != null ) {
231 writer.println( makeUniqSeq( clmNo,data ) );
232 writer.println( makeUniqTrig( clmNo,data, uniqName ) );
233 }
234
235 if( isXml ) { writer.println( XML_END_TAG ); }
236 writer.close();
237 }
238 catch( RuntimeException ex ) {
239 ErrorMessage errMessage = makeErrorMessage( "TableFilter_TABLE Error",ErrorMessage.NG );
240 // errMessage.addMessage( row+1,ErrorMessage.NG,"TABLE",ex.getMessage() );
241 errMessage.addMessage( row+1,ErrorMessage.NG,"TABLE",ex.toString() );
242 errMessage.addMessage( row+1,ErrorMessage.NG,"TABLE",StringUtil.array2csv( data ) );
243 errMessage.addMessage( row+1,ErrorMessage.NG,"TABLE","TABLE=[" + tableName + "]" );
244 // BAT から呼び出す?合があるため、標準エラー出力にも情報を?しておきます?
245 System.out.println( errMessage );
246 }
247 }
248
249 return table;
250 }
251
252 /**
253 * ヘッ??部??処?実行します?
254 *
255 * @og.rev 5.6.6.0 (2013/07/05) FixLengthData の簡易コンストラクタを使用
256 * @og.rev 5.6.6.2 (2013/07/19) EXEC_START_TAG の付け忘れ
257 *
258 * @param clmNo カラ?号配?
259 * @param data ?行?の??タ配?
260 *
261 * @return ヘッ??部????
262 */
263 protected String makeHeadLine( final int[] clmNo,final String[] data ) {
264 final String TBL_NAME = data[clmNo[TABLE_NAME]];
265
266 String LINE1 = TBL_NAME + " ( " + data[clmNo[NAME_JA]] + " )" ;
267 String LINE2 = data[clmNo[COMMENTS]] ;
268 String LINE3 = "Created : " + HybsSystem.getDate() ;
269
270 // 5.6.6.0 (2013/07/05) FixLengthData の簡易コンストラクタを使用
271 // FixLengthData fixData = new FixLengthData(3);
272
273 int[] addLen = new int[] { 0,0,0 }; // ?ータ間?スペ?ス
274 int[] type = new int[] { X,K,X }; // ?ータの種別 X:半?S:空白前埋?K:全角混在
275 // fixData.setAddLength( addLen );
276 // fixData.setType( type );
277 FixLengthData fixData = new FixLengthData( addLen,type );
278
279 String[][] outData = new String[][] {
280 { "/**", CMNT , "**/" },
281 { "/* ", LINE1, " */" },
282 { "/* ", LINE2, " */" },
283 { "/* ", LINE3, " */" },
284 { "/**", CMNT , "**/" },
285 };
286
287 fixData.addAllListData( outData );
288
289 // for( int i=0; i<outData.length; i++ ) {
290 // fixData.addListData( outData[i] );
291 // }
292
293 // StringBuilder buf = new StringBuilder();
294 // if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); }
295 // for( int i=0; i<outData.length; i++ ) {
296 // buf.append( fixData.getFixData( i ) ).append( CR );
297 // }
298
299 StringBuilder buf = new StringBuilder();
300 fixData.getAllFixData( buf );
301
302 if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); } // 5.6.6.2 (2013/07/19) 出力忘れ
303
304 buf.append( "CREATE TABLE " ).append( TBL_NAME ).append( " (" ).append( CR );
305
306 return buf.toString();
307 }
308
309 /**
310 * ?部?カラ?義)の処?実行します?
311 * カン?カラ?クラス,(,桁数,),初期値,NOT_NULL,拡張機?,コメント開?行番号,名称,コメント終?
312 * の?配?にセ?します?
313 *
314 * @og.rev 5.5.1.9 (2012/04/18) useLen.length=0対?
315 * @param data ?行?の??タ配?
316 * @param first ??の行かど?[true:??/false:それ以降]
317 *
318 * @return ?部?カラ?義)配?
319 */
320 protected String[] makeLineList( final String[] data,final boolean first ) {
321 // カン?カラ?クラス(桁数),初期値,NOT_NULL,独自拡張,行番号,名称,終?
322 String[] outData = new String[13];
323 String clsName = data[GF05_CLS_NAME];
324
325 outData[0] = ( first ) ? " " : " , " ; // 0:カン?
326 outData[1] = data[GF05_CLM] ; // 1:カラ?
327
328 if( clsName.startsWith( "CLOB" ) || clsName.startsWith( "DATE" ) ) {
329 data[GF05_USE_LENGTH] = null;
330 }
331 String useLen = data[GF05_USE_LENGTH];
332 // if( useLen != null && ! useLen.equals( "0" ) ) {
333 if( useLen != null && ! useLen.equals( "0" ) && useLen.length() > 0 ) { // 5.5.1.9 (2012/04/18)
334 // outData[2] = clsName + "(" + useLen + ")" ; // 2:クラス(桁数)
335 outData[2] = clsName ; // 2:クラス
336 outData[3] = " ( " ; // 3:(
337 outData[4] = useLen ; // 4:桁数
338 outData[5] = " )" ; // 5:)
339 }
340 else {
341 outData[2] = clsName ; // NUMBER型?桁数?なし?ケース
342 }
343
344 String def = data[GF05_DATA_DEFAULT];
345 if( def != null && def.length() > 0 ) {
346 String comma = ( clsName.indexOf( "CHAR" ) >= 0 ) ? "'" : "" ;
347 outData[6] = "DEFAULT " + comma + def + comma ; // 6:初期値
348 }
349
350 String notNull = data[GF05_NOT_NULL];
351 if( notNull != null && notNull.equals( "1" ) ) {
352 outData[7] = "NOT NULL" ; // 7:NOT_NULL
353 }
354
355 String options = data[GF05_OPTIONS];
356 if( options != null ) {
357 outData[8] = options ; // 8:拡張機?
358 }
359
360 String nameJA = data[GF05_NAME_JA] ; // 名称
361 if( nameJA != null ) {
362 outData[9] = "/* " ; // 9:コメント開?
363 outData[10] = data[GF05_SEQNO] ; // 10:行番号
364 outData[11] = nameJA ; // 11:名称
365 outData[12] = "*/" ; // 12:コメント終?
366 }
367
368 return outData ;
369 }
370
371 /**
372 * 定義の??部??処?実行します?
373 *
374 * @param clmNo カラ?号配?
375 * @param data ?行?の??タ配?
376 *
377 * @return 定義の??部?
378 */
379 protected String makeEndLine( final int[] clmNo,final String[] data ) {
380 StringBuilder buf = new StringBuilder();
381
382 buf.append( ")" ).append( CR );
383 buf.append( "TABLESPACE " ).append( data[clmNo[TABLESPACE_NAME]] ).append( CR );
384 buf.append( "STORAGE( INITIAL " ).append( data[clmNo[INITIAL_EXTENT]] );
385 buf.append( "K NEXT " ).append( data[clmNo[NEXT_EXTENT]] );
386 buf.append( "K PCTINCREASE 0 )" );
387
388 if( isXml ) { buf.append( CR ).append( EXEC_END_TAG ); }
389 else { buf.append( ";" ); }
390
391 return buf.toString();
392 }
393
394 /**
395 * ユニ?クシーケンスの作?処?実行します?
396 *
397 * @og.rev 5.1.9.0 (2010/08/01) シーケンス名を[TABLE_NAME]S00に変更
398 *
399 * @param clmNo カラ?号配?
400 * @param data ?行?の??タ配?
401 *
402 * @return ユニ?クシーケンス
403 */
404 protected String makeUniqSeq( final int[] clmNo,final String[] data ) {
405 StringBuilder buf = new StringBuilder();
406
407 buf.append( CR );
408 if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); }
409
410 // 5.1.9.0 (2010/08/01) シーケンス名を[TABLE_NAME]S00に変更
411 // buf.append( "CREATE SEQUENCE " ).append( data[clmNo[TABLE_NAME]] ).append( "S01 " ).append( CR );
412 buf.append( "CREATE SEQUENCE " ).append( data[clmNo[TABLE_NAME]] ).append( "S00 " ).append( CR );
413 buf.append( " INCREMENT BY 1 START WITH 1 MAXVALUE 999999999 CYCLE NOCACHE" );
414 // buf.append( "INCREMENT BY 1 ");
415 // buf.append( "START WITH 1 " );
416 // buf.append( "MAXVALUE 999999999 " );
417 // buf.append( "CYCLE NOCACHE" );
418
419 if( isXml ) { buf.append( CR ).append( EXEC_END_TAG ); }
420 else { buf.append( ";" ); }
421
422 return buf.toString();
423 }
424
425 /**
426 * ユニ?クシーケンスと関連付けるトリガの作?処?実行します?
427 *
428 * @og.rev 5.1.9.0 (2010/08/01) トリガー名を[TABLE_NAME]T00に変更
429 *
430 * @param clmNo カラ?号配?
431 * @param data ?行?の??タ配?
432 * @param uniqName ユニ?クトリガ?
433 *
434 * @return ユニ?クシーケンスと関連付けるトリガ
435 */
436 protected String makeUniqTrig( final int[] clmNo,final String[] data, final String uniqName ) {
437 final String TBL_NAME = data[clmNo[TABLE_NAME]] ;
438 StringBuilder buf = new StringBuilder();
439
440 buf.append( CR );
441 if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); }
442
443 // 5.1.9.0 (2010/08/01) トリガー名を[TABLE_NAME]T00に変更
444 // buf.append( "CREATE OR REPLACE TRIGGER " ).append( TBL_NAME ).append( "T01 " ).append( CR );
445 buf.append( "CREATE OR REPLACE TRIGGER " ).append( TBL_NAME ).append( "T00 " ).append( CR );
446 buf.append( " BEFORE INSERT ON ").append( TBL_NAME ).append( CR );
447 buf.append( " FOR EACH ROW " ).append( CR );
448 buf.append( " BEGIN " ).append( CR );
449 // 5.1.9.0 (2010/08/01) シーケンス名を[TABLE_NAME]S00に変更
450 // buf.append( "SELECT " ).append( TBL_NAME ).append( "S01.NEXTVAL INTO :NEW." )
451 buf.append( " SELECT " ).append( TBL_NAME ).append( "S00.NEXTVAL INTO :NEW." )
452 .append( uniqName ).append( " FROM DUAL; " ).append( CR );
453 buf.append( " END; " ).append( CR );
454
455 if( isXml ) { buf.append( EXEC_END_TAG ); }
456 else { buf.append( "/" ); }
457
458 return buf.toString();
459 }
460 }