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