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; 020 021import org.opengion.fukurou.system.OgBuilder ; // 6.4.4.1 (2016/03/18) 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; 030 031/** 032 * TableFilter_SEQUENCE は、TableUpda インターフェースを継承した、DBTableModel 処理用の 033 * 実装クラスです。 034 * 035 * ここでは、シーケンス一覧の検索結果より、GF09 のシーケンス定義テーブルから 036 * 必要な情報を取得し、シーケンス作成スクリプトを作成します。 037 * 038 * この処理を実行するには、DBTableModelのカラムとして、 039 * SYSTEM_ID,TBLSYU,SEQNAME,INCREBY,STARTVAL,MINVAL,MAXVAL,FGCYCLE,SUCACHE 040 * が必要です。 041 * 042 * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか、BODY 部にCSS形式で記述します。 043 * 【パラメータ】 044 * { 045 * DIR : {@BASE_DIR}/sql/install/03_SEQ ; 出力ファイルの基準フォルダ(必須) 046 * XML : false ; XML出力を行うかどうか[true/false]を指定します(初期値:false)。 047 * } 048 * 049 * @og.formSample 050 * ●形式: 051 * select SYSTEM_ID,TBLSYU,SEQNAME,INCREBY,STARTVAL,MINVAL,MAXVAL,FGCYCLE,SUCACHE from GF09 052 * 053 * ① <og:tableFilter classId="SEQUENCE" keys="DIR,XML" vals='"{@BASE_DIR}/sql/install/03_SEQ,"' /> 054 * 055 * ② <og:tableFilter classId="SEQUENCE" > 056 * { 057 * DIR : {@BASE_DIR}/sql/install/03_SEQ ; 058 * XML : false ; 059 * } 060 * </og:tableFilter> 061 * 062 * @og.rev 5.1.9.0 (2010/08/01) DB定義DB・シーケンス定義追加 063 * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを追加 064 * 065 * @version 0.9.0 2010/08/01 066 * @author Hiroki Nakamura 067 * @since JDK1.1, 068 */ 069public class TableFilter_SEQUENCE extends AbstractTableFilter { 070 /** このプログラムのVERSION文字列を設定します。 {@value} */ 071 private static final String VERSION = "6.5.0.1 (2016/10/21)" ; 072 073 private static final String[] DBKEY = {"SYSTEM_ID","TBLSYU","SEQNAME","INCREBY","STARTVAL","MINVAL","MAXVAL","FGCYCLE","SUCACHE" }; 074 075 /** データのアクセス用の配列番号 {@value} */ 076 protected static final int SYSTEM_ID = 0; 077 /** データのアクセス用の配列番号 {@value} */ 078 protected static final int TBLSYU = 1; 079 /** データのアクセス用の配列番号 {@value} */ 080 protected static final int SEQNAME = 2; 081 /** データのアクセス用の配列番号 {@value} */ 082 protected static final int INCREBY = 3; 083 /** データのアクセス用の配列番号 {@value} */ 084 protected static final int STARTVAL = 4; 085 /** データのアクセス用の配列番号 {@value} */ 086 protected static final int MINVAL = 5; 087 /** データのアクセス用の配列番号 {@value} */ 088 protected static final int MAXVAL = 6; 089 /** データのアクセス用の配列番号 {@value} */ 090 protected static final int FGCYCLE = 7; 091 /** データのアクセス用の配列番号 {@value} */ 092 protected static final int SUCACHE = 8; 093 094 private static final String ENCODE = "UTF-8" ; // 4.3.6.6 (2009/05/15) 095 096 private static final String CMNT = "************************************************************************" ; 097 098 private static final int X = FixLengthData.X ; 099 private static final int K = FixLengthData.K ; 100 101 /** 各種定数 */ 102 // 6.0.2.3 (2014/10/10) AbstractTableFilter へ移動 103 104 /** XML形式かどうか */ 105 106 /** 107 * デフォルトコンストラクター 108 * 109 * @og.rev 6.4.1.1 (2016/01/16) keysMap を、サブクラスから設定させるように変更。 110 */ 111 public TableFilter_SEQUENCE() { 112 super(); 113 initSet( "DIR" , "出力ファイルの基準フォルダ(必須)" ); 114 initSet( "XML" , "XML出力を行うかどうか[true/false]を指定(初期値:false)" ); 115 } 116 117 /** 118 * DBTableModel処理を実行します。 119 * 120 * @og.rev 5.5.2.6 (2012/05/25) protected変数を、private化したため、getterメソッドで取得するように変更 121 * @og.rev 6.0.2.3 (2014/10/10) EXEC_END_TAG 自体にCRを追加。キャッシュします。 122 * @og.rev 6.3.7.0 (2015/09/04) AutoCloseableを使用したtry-with-resources構築に対応。 123 * @og.rev 6.5.0.1 (2016/10/21) ErrorMessage をまとめるのと、直接 Throwable を渡します。 124 * 125 * @return 実行結果のテーブルモデル 126 */ 127 public DBTableModel execute() { 128 isXml = StringUtil.nval( getValue( "XML" ), false ); 129 execEndTag = isXml ? CR + EXEC_END_TAG : ";" ; // 6.0.2.3 (2014/10/10) 130 131 final File dir = new File( getValue( "DIR" ) ); 132 if( ! dir.exists() && ! dir.mkdirs() ) { 133 final String errMsg = "所定のフォルダが作成できませんでした。[" + dir + "]" ; 134 // 4.3.4.4 (2009/01/01) 135 throw new HybsSystemException( errMsg ); 136 } 137 138 // 6.3.9.1 (2015/11/27) Found 'DD'-anomaly for variable(PMD) 139 final int[] clmNo = getTableColumnNo( DBKEY ); 140 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid declaring a variable if it is unreferenced before a possible exit point. 141 final DBTableModel table = getDBTableModel(); // 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 142 final int rowCnt = table.getRowCount(); 143 for( int row=0; row<rowCnt; row++ ) { 144 final String[] data = table.getValues( row ); // 6.3.9.1 (2015/11/27) 145 final String seqName = data[clmNo[SEQNAME]]; 146 // 6.3.7.0 (2015/09/04) AutoCloseableを使用したtry-with-resources構築に対応。 147 try( final PrintWriter writer = FileUtil.getPrintWriter( new File( dir,seqName + ( isXml ? ".xml" : ".sql" ) ),ENCODE ) ) { 148 if( isXml ) { writer.println( XML_START_TAG ); } 149 writer.print( makeHeadLine( clmNo,data ) ); 150 writer.println( makeLineList( clmNo,data ) ); 151 if( isXml ) { writer.println( XML_END_TAG ); } 152 } 153 catch( final RuntimeException ex ) { // catch は、close() されてから呼ばれます。 154 // 6.5.0.1 (2016/10/21) ErrorMessage をまとめるのと、直接 Throwable を渡します。 155 final ErrorMessage errMessage = makeErrorMessage( "TableFilter_SEQNENCE Error",ErrorMessage.NG ) 156 .addMessage( row+1,ErrorMessage.NG,"SEQUENCE" 157 , "SEQ=[" + seqName + "]" 158 , StringUtil.array2csv( data ) 159 ) 160 .addMessage( ex ); 161 // BAT から呼び出す場合があるため、標準エラー出力にも情報を出しておきます。 162 System.out.println( errMessage ); 163 } 164 } 165 166 return table; 167 } 168 169 /** 170 * ヘッダー部分の処理を実行します。 171 * 172 * @og.rev 5.6.6.0 (2013/07/05) FixLengthData の簡易コンストラクタを使用 173 * 174 * @param clmNo カラム番号配列 175 * @param data 1行分のデータ配列 176 * 177 * @return ヘッダー部分の文字列 178 * @og.rtnNotNull 179 */ 180 protected String makeHeadLine( final int[] clmNo,final String[] data ) { 181 final String seqName = data[clmNo[SEQNAME]]; 182 final String LINE1 = seqName; 183 final String LINE2 = "Created : " + HybsSystem.getDate() ; 184 185 // 5.6.6.0 (2013/07/05) FixLengthData の簡易コンストラクタを使用 186 final int[] addLen = new int[] { 0,0,0 }; // 各データ間のスペース 187 final int[] type = new int[] { X,K,X }; // 各データの種別 X:半角 S:空白前埋め K:全角混在 188 final FixLengthData fixData = new FixLengthData( addLen,type ); 189 190 final String[][] outData = new String[][] { 191 { "/**", CMNT , "**/" }, 192 { "/* ", LINE1, " */" }, 193 { "/* ", LINE2, " */" }, 194 { "/**", CMNT , "**/" }, 195 }; 196 197 fixData.addAllListData( outData ); 198 199 return fixData.getAllFixData(); 200 } 201 202 /** 203 * シーケンス作成の処理を実行します。 204 * 205 * @og.rev 6.0.2.3 (2014/10/10) isXml で、CR + EXEC_END_TAG のキャッシュ(execEndTag)を利用します。 206 * @og.rev 6.4.4.1 (2016/03/18) StringBuilderの代わりに、OgBuilderを使用する。 207 * 208 * @param clmNo カラム番号配列 209 * @param data 1行分のデータ配列 210 * 211 * @return シーケンス作成 212 * @og.rtnNotNull 213 */ 214 protected String makeLineList( final int[] clmNo,final String[] data ) { 215 return new OgBuilder() 216 .appendIfCR( isXml , EXEC_START_TAG ) 217 .appendCR( "CREATE SEQUENCE " , data[clmNo[SEQNAME]] ) 218 .append( " START WITH " , data[clmNo[STARTVAL]] ) 219 .append( " INCREMENT BY " , data[clmNo[INCREBY]] ) 220 .append( " MINVALUE " , data[clmNo[MINVAL]] ) 221 .append( " MAXVALUE " , data[clmNo[MAXVAL]] ) 222 .appendCase( "1".equals( data[clmNo[FGCYCLE]] ) // flagで選択されます。 223 , " CYCLE" , " NOCYCLE" ) // true , false 224 .appendCase( Integer.parseInt( data[clmNo[SUCACHE]] ) <= 0 // 注意:判定条件を反転してます。 225 , " NOCACHE" // true 226 , " CACHE " , data[clmNo[SUCACHE]] ) // false 227 .append( execEndTag ) 228 .toString(); 229 } 230}