    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 * 画面作成するにあたり、３箇所の参照元が存在します。
    043 *
    044 *   １．画面属性の設定 ： 雛形   → 仮画面   ・・・ hpgid で指定の画面ID
    045 *   ２．仮画面修正     ： 仮画面 → 仮画面   ・・・ jsp/customUserDef/画面ID
    046 *   ３．本環境修正     ： 本画面 → 本画面   ・・・ jsp/画面ID
    047 *
    048 * それぞれ、作成先の画面IDフォルダが存在する場合は、取込元を作成先に設定します。
    049 * つまり、一度作成すると、それ以降は、作成された画面を基準に処理を行います。
    050 *
    051 * @og.formSample
    052 * ●形式：&lt;og:jspCreate outdir="…" pgid="…" /&gt;
    053 * ●body：なし
    054 *
    055 * ●Tag定義：
    056 *   &lt;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 *   /&gt;
    066 *
    067 * ●使用例
    068 *    ・先に、query タグでDBTableModel が作成済み
    069 *          &lt;og:jspCreate
    070 *              outdir      = "{&#064;SYS.REAL_PATH}jsp/"    ：出力先フォルダ
    071 *              pgid        = "{&#064;PGID}"                 ：作成画面ID
    072 *              hpgid       = "{&#064;HPGID}"                ：雛形画面ID
    073 *              useUserDef  = "true/false"                   ：仮環境の使用可否(初期値:true 使用する)
    074 *          /&gt;
    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}