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.hayabusa.taglib; 017 018import org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.hayabusa.common.HybsSystemException; 020import org.opengion.hayabusa.db.DBTableModel; 021import org.opengion.hayabusa.develop.JspCreateFactory; 022import org.opengion.hayabusa.develop.JspConvertEntity; 023import org.opengion.fukurou.util.ErrorMessage; 024import org.opengion.fukurou.util.StringUtil; 025import static org.opengion.fukurou.util.StringUtil.nval ; 026import org.opengion.fukurou.xml.JspSaxParser; 027 028import java.util.Map; 029import java.util.HashMap; 030import java.util.List; 031import java.util.ArrayList; 032import java.util.Locale ; 033 034import java.io.File; 035import java.io.ObjectOutputStream; 036import java.io.ObjectInputStream; 037import java.io.IOException; 038 039/** 040 * JspCreateTag は、画面定義情報より、JSP画面を自動作成するツールです。 041 * 042 * 画面作成するにあたり、3箇所の参照元が存在します。 043 * 044 * 1.画面属性の設定 : 雛形 → 仮画面 ・・・ hpgid で指定の画面ID 045 * 2.仮画面修正 : 仮画面 → 仮画面 ・・・ jsp/customUserDef/画面ID 046 * 3.本環境修正 : 本画面 → 本画面 ・・・ jsp/画面ID 047 * 048 * それぞれ、作成先の画面IDフォルダが存在する場合は、取込元を作成先に設定します。 049 * つまり、一度作成すると、それ以降は、作成された画面を基準に処理を行います。 050 * 051 * @og.formSample 052 * ●形式:<og:jspCreate outdir="…" pgid="…" /> 053 * ●body:なし 054 * 055 * ●Tag定義: 056 * <og:jspCreate 057 * pgid ○【TAG】プログラムIDを指定します(必須)。 058 * outdir 【TAG】作成先のディレクトリを指定します 059 * hpgid 【TAG】雛形のプログラムIDを指定します 060 * useUserDef 【TAG】仮環境を使用するかどうか[true/false]を指定します(初期値:true:使用する) 061 * tagNames 【TAG】処理を行うタグを部分指定します(初期値:内部登録タグすべて) 062 * tableId 【TAG】(通常は使いません)DBTableModel が登録されているメモリのキーを指定します 063 * scope 【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session) 064 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 065 * /> 066 * 067 * ●使用例 068 * ・先に、query タグでDBTableModel が作成済み 069 * <og:jspCreate 070 * outdir = "{@SYS.REAL_PATH}jsp/" :出力先フォルダ 071 * pgid = "{@PGID}" :作成画面ID 072 * hpgid = "{@HPGID}" :雛形画面ID 073 * useUserDef = "true/false" :仮環境の使用可否(初期値:true 使用する) 074 * /> 075 * 076 * @og.group 開発補助 077 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 078 * 079 * @version 0.9.0 2000/10/17 080 * @author Kazuhiko Hasegawa 081 * @since JDK1.6, 082 */ 083public class JspCreateTag extends CommonTagSupport { 084 //* このプログラムのVERSION文字列を設定します。 {@value} */ 085 private static final String VERSION = "5.6.8.0 (2013/09/06)" ; 086 087 private static final long serialVersionUID = 568020130906L ; 088 089 private static String JSP_DIR = HybsSystem.sys( "REAL_PATH" ) + "jsp/" ; 090 091 private static final String CUST_DEF = "customUserDef/" ; 092 093 private transient DBTableModel table = null; 094 095 private String tableId = HybsSystem.TBL_MDL_KEY; 096 private String outdir = JSP_DIR; // 出力先フォルダ 097 private String pgid = null; // 作成画面ID 098 private String hpgid = null; // 雛形画面ID 099 private String[] tagNames = null; // 5.6.8.0 (2013/09/06) 処理を行うタグを部分指定 100 private boolean useUserDef = true; // 仮環境の使用可否(初期値:true 使用する) 101 102 private static final String[] JCF_LIST = new String[] { "COMMENT" , "HIDEMENU" , "COLUMN" , "ORDER_BY" , "QUERY" , "VIEW" , "TABLE_UPDATE" }; // 5.6.4.4 (2013/05/31) 103 104 /** 105 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 106 * 107 * @return 後続処理の指示(SKIP_BODY) 108 */ 109 @Override 110 public int doStartTag() { 111 table = (DBTableModel)getObject( tableId ); 112 113 return SKIP_BODY ; // Body を評価しない 114 } 115 116 /** 117 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 118 * 119 * @return 後続処理の指示 120 */ 121 @Override 122 public int doEndTag() { 123 // デバッグ時には、オブジェクト内部情報を表示する。 124 if( isDebug() ) { 125 debugPrint(); 126 } 127 128 boolean okFlag = execute(); 129 130 if( okFlag ) { // 正常 131 return EVAL_PAGE ; 132 } 133 else { 134 return SKIP_PAGE ; 135 } 136 } 137 138 /** 139 * タグリブオブジェクトをリリースします。 140 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 141 * 142 * @og.rev 5.6.8.0 (2013/09/06) tagNames 追加 143 */ 144 @Override 145 protected void release2() { 146 super.release2(); 147 table = null; 148 tableId = HybsSystem.TBL_MDL_KEY; 149 outdir = JSP_DIR; 150 pgid = null; 151 hpgid = null; 152 useUserDef = true; 153 tagNames = null; // 5.6.8.0 (2013/09/06) 処理を行うタグを部分指定 154 } 155 156 /** 157 * DBTableModel処理を実行します。 158 * 159 * @og.rev 5.2.1.0 (2010/10/01) 実行クラスのクラス名を変更します。 _OG_ を削除 160 * @og.rev 5.5.2.6 (2012/05/25) findbugs対応。JspConvertEntity.DBKEY を、JspConvertEntity.getDBKEY() に変更。 161 * @og.rev 5.6.8.0 (2013/09/06) 処理対象タグの部分指定対応 (tagNames 追加) 162 * 163 * @return 処理の実行結果 164 */ 165 public boolean execute() { 166 boolean okFlag = false; 167 168 // 出力先(セーブ先)のフォルダ 169 File saveDir = useUserDef ? new File( outdir + CUST_DEF , pgid ) : new File( outdir , pgid ) ; 170 171 // 雛形(参照元)のフォルダ 172 final File refDir ; 173 if( saveDir.exists() ) { // 出力先フォルダが存在した場合 174 refDir = saveDir ; // 出力先フォルダが、雛形フォルダになる。 175 } 176 else { // 出力先フォルダが存在しない場合 177 refDir = new File( outdir , hpgid ); // 雛形画面IDをそのまま使用します。 178 if( ! saveDir.mkdirs() ) { 179 String errMsg = "出力先のフォルダが作成できませんでした。[" + saveDir + "]" ; 180 throw new HybsSystemException( errMsg ); 181 } 182 } 183 184 if( ! refDir.exists() ) { // 雛形(参照元)フォルダが存在しない場合、エラー 185 String errMsg = "雛形(参照元)フォルダが存在しません。[" + refDir + "]" ; 186 throw new HybsSystemException( errMsg ); 187 } 188 189 int[] clmNo = getTableColumnNo( JspConvertEntity.getDBKEY() ); // 5.5.2.6 (2012/05/25) findbugs対応 190 int rowCnt = table.getRowCount(); 191 192 int row = 0; 193 boolean unCmntSet = true; 194 String[] data = null; 195 try { 196 //JSPを書く為に必要な情報を設定 197 Map<String,List<JspConvertEntity>> tables = new HashMap<String,List<JspConvertEntity>>(); 198 199 for( row=0; row<rowCnt; row++ ) { 200 data = table.getValues( row ); 201 JspConvertEntity entry = JspConvertEntity.newInstance( data, clmNo ); 202 203 if( entry != null ) { 204 List<JspConvertEntity> array = tables.get( entry.getType() ); 205 if( array == null ) { array = new ArrayList<JspConvertEntity>(); } 206 array.add( entry ); 207 tables.put( entry.getType(),array ); 208 if( unCmntSet ) { 209 tables.put( "COMMENT",array ); 210 unCmntSet = false; 211 } 212 } 213 } 214 215 // 参照先フォルダから、出力先フォルダに、XMLコピー処理を行います。 216 JspSaxParser spar = new JspSaxParser(); 217 218 // 5.2.1.0 (2010/10/01) 実行クラスのクラス名を変更します。 _OG_ を削除 219 // 5.6.8.0 (2013/09/06) 処理対象タグの部分指定対応 (tagNames 追加) 220 if( tagNames == null ) { tagNames = JCF_LIST; } 221 for( String jcf : tagNames ) { 222 spar.addFilter( JspCreateFactory.newInstance( jcf , tables ) ); 223 } 224 225 spar.copyDirectry( refDir,saveDir ); 226 227 okFlag = true; 228 } 229 catch( RuntimeException ex ) { 230 ex.printStackTrace(); 231 ErrorMessage errMessage = new ErrorMessage( "JspCreateTag Error" ); 232 errMessage.addMessage( row+1,ErrorMessage.NG,"JSPOUT",ex.getMessage() ); 233 errMessage.addMessage( row+1,ErrorMessage.NG,"JSPOUT",StringUtil.array2csv( data ) ); 234 errMessage.addMessage( row+1,ErrorMessage.NG,"JSPOUT","PRGID=[" + pgid + "]" ); 235 // BAT から呼び出す場合があるため、標準エラー出力にも情報を出しておきます。 236 System.out.println( errMessage ); 237 } 238 239 return okFlag; 240 } 241 242 /** 243 * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します 244 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。 245 * 246 * @og.tag 247 * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に 248 * 渡す場合に、通常は、session を利用します。その場合の登録キーです。 249 * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、 250 * この tableId 属性を利用して、メモリ空間を分けます。 251 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。 252 * 253 * @param id sessionに登録する時の ID 254 */ 255 public void setTableId( final String id ) { 256 tableId = nval( getRequestParameter( id ),tableId ); 257 } 258 259 /** 260 * 【TAG】作成先のディレクトリを指定します。 261 * 262 * @og.tag 263 * 作成先のディレクトリを指定します。 264 * 初期値は、実際に実行しているアプリケーションの REAL_PATH + jsp フォルダ以下です。 265 * 作成先のフォルダも、useUserDef の設定によって異なります。 266 * 267 * @param dir 出力先のディレクトリ 268 */ 269 public void setOutdir( final String dir ) { 270 outdir = nval( getRequestParameter( dir ),outdir ); 271 } 272 273 /** 274 * 【TAG】プログラムIDを指定します。 275 * 276 * @og.tag 277 * 作成先のプログラムIDを指定します。 278 * ただし、作成先の実際のフォルダは、useUserDef の設定によって異なります。 279 * 280 * @param id プログラムID 281 */ 282 public void setPgid( final String id ) { 283 pgid = nval( getRequestParameter( id ),pgid ); 284 } 285 286 /** 287 * 【TAG】雛形のプログラムIDを指定します。 288 * 289 * @og.tag 290 * 雛形のプログラムIDをパースして、実際のプログラムを作成します。 291 * ただし、作成先の実際のフォルダは、useUserDef の設定によって異なります。 292 * また、パースするのは、作成先の画面IDのフォルダが存在しない場合のみです。 293 * すでに、存在している場合は、元の画面IDのフォルダを読み取って、パースを 294 * 行います。基本的に、作成先のソースを手で修正した場合でも、パースと 295 * 無関係な箇所の修正はそのまま反映のこされます。 296 * 297 * @param id 雛形のプログラムID 298 */ 299 public void setHpgid( final String id ) { 300 hpgid = nval( getRequestParameter( id ),hpgid ); 301 } 302 303 /** 304 * 【TAG】仮環境を使用するかどうか[true/false]を指定します(初期値:true:使用する)。 305 * 306 * @og.tag 307 * true:使用する を設定すると、"customUserDef" フォルダの下に、画面IDの 308 * フォルダを作成します。 309 * false:使用しない を設定すると、実際の リアルパス(REAL_PATH/jsp)の下に、 310 * 画面IDのフォルダを作成します。こちらは、実際の画面と同様に、画面リソース等を 311 * 作成してアクセスすることになります。 312 * 313 * @param flag 仮環境を使用するかどうか [true:使用する/false:使用しない] 314 */ 315 public void setUseUserDef( final String flag ) { 316 useUserDef = nval( getRequestParameter( flag ),useUserDef ); 317 } 318 319 /** 320 * 【TAG】処理を行うタグを部分指定します(初期値:内部登録タグすべて)。 321 * 322 * @og.tag 323 * 処理を行うタグは、内部的に、COMMENT,HIDEMENU,COLUMN,ORDER_BY,QUERY,VIEW,TABLE_UPDATE だけ 324 * 予約されており、初期値は、すべてのタグを処理します。 325 * ここでは、その一部のみ実行できるように、カンマ区切り文字で指定できるようにします。 326 * 実行不可のタグ名を指定すると、エラーになります。 327 * 328 * @og.rev 5.6.8.0 (2013/09/06) 新規追加 329 * 330 * @param tags 処理を行うタグを部分指定する。 331 */ 332 public void setTagNames( final String tags ) { 333 String tagNms = nval( getRequestParameter( tags ),null ); 334 335 if( tagNms != null ) { 336 tagNames = tagNms.split( "," ); 337 338 for( int i=0; i<tagNames.length; i++ ) { 339 String tag = tagNames[i].trim().toUpperCase(Locale.JAPAN); 340 if( ! check( tag, JCF_LIST ) ) { 341 String errMsg = "指定の tagNames は、下記の範囲で指定してください。" 342 + "tagNames=" + tagNms + " (NG=" + tag + ") : " 343 + JCF_LIST.toString(); 344 throw new HybsSystemException( errMsg ); 345 } 346 tagNames[i] = tag ; // 大文字に変換した値を戻す。 347 } 348 } 349 } 350 351 /** 352 * カラム名配列(String[])より、対応するカラムNo配列(int[])を作成します。 353 * 354 * @param nameArray カラム名配列 355 * 356 * @return カラムNo配列 357 */ 358 private int[] getTableColumnNo( final String[] nameArray ) { 359 int[] clmNo = new int[ nameArray.length ]; 360 for( int i=0; i<clmNo.length; i++ ) { 361 clmNo[i] = table.getColumnNo( nameArray[i] ); 362 } 363 return clmNo; 364 } 365 366 /** 367 * シリアライズ用のカスタムシリアライズ書き込みメソッド 368 * 369 * @param strm ObjectOutputStreamオブジェクト 370 * @serialData 一部のオブジェクトは、シリアライズされません。 371 * 372 * @throws IOException 入出力エラーが発生した場合 373 */ 374 private void writeObject( final ObjectOutputStream strm ) throws IOException { 375 strm.defaultWriteObject(); 376 } 377 378 /** 379 * シリアライズ用のカスタムシリアライズ読み込みメソッド 380 * 381 * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。 382 * 383 * @param strm ObjectInputStreamオブジェクト 384 * @see #release2() 385 * @serialData 一部のオブジェクトは、シリアライズされません。 386 * 387 * @throws IOException シリアライズに関する入出力エラーが発生した場合 388 * @throws ClassNotFoundException クラスを見つけることができなかった場合 389 */ 390 private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException { 391 strm.defaultReadObject(); 392 } 393 394 /** 395 * このオブジェクトの文字列表現を返します。 396 * 基本的にデバッグ目的に使用します。 397 * 398 * @return このクラスの文字列表現 399 */ 400 @Override 401 public String toString() { 402 return org.opengion.fukurou.util.ToString.title( this.getClass().getName() ) 403 .println( "VERSION" ,VERSION ) 404 .println( "tableId" ,tableId ) 405 .println( "outdir" ,outdir ) 406 .println( "pgid" ,pgid ) 407 .println( "hpgid" ,hpgid ) 408 .println( "useUserDef" ,useUserDef ) 409 .fixForm().toString() ; 410 } 411}