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.hayabusa.taglib;
017    
018    import org.opengion.hayabusa.common.HybsSystem;
019    import org.opengion.hayabusa.common.HybsSystemException;
020    import org.opengion.hayabusa.db.DBTableModel;
021    import org.opengion.hayabusa.db.TableFilter;
022    import org.opengion.fukurou.db.Transaction;
023    import org.opengion.fukurou.db.TransactionReal;
024    import org.opengion.fukurou.util.ErrorMessage;
025    import org.opengion.fukurou.util.StringUtil;
026    import static org.opengion.fukurou.util.StringUtil.nval ;
027    
028    import java.io.ObjectOutputStream;
029    import java.io.ObjectInputStream;
030    import java.io.IOException;
031    import java.util.Map;
032    
033    /**
034     * TableFilter のサブクラスをCALLしてDBTableModelにアクセスするタグです?
035     *
036     * DBTableModel ?TableFilter のサブクラス(classIdで??に渡して処?実行します?
037     * クラスを作?する場合?、org.opengion.hayabusa.db.TableFilter インターフェースを継承した
038     * クラスにする?があります?また?classId 属?には、シス?リソース で
039     * 設定し?TableFilter.XXXX の XXXX を指定します?
040     *
041     * BODY部??、SQLを記述する為?に使って?したが?CSS定義形式?書式で、keys,vals を記述
042     * できるようにします?
043     * これは、下記?ようなパラメータを?keys="KEY,KEY2,KEY3" vals='AAAA,"BB,CC,DD",EE' のような記述形式と
044     *   {
045     *        KEY1 : AAAA ;
046     *        KEY2 : BB,CC,DD ;
047     *        KEY3 : EE ;
048     *        ・・・・・・
049     *   }
050     * のような、CSS形式に類似の形式でも記述できるようにしました?
051     * keys,vals と CSS定義形式パラメータを同時に?した?合?、両方とも有効です?
052     * ただし?キーが重?た?合?、不定と?てください?
053     * 現時点では、CSS定義形式パラメータが優先されますが、これ?、単に?パラメータMapへの
054     * 登録?、CSS定義形式パラメータが後?為、上書きされるためです?
055     *
056     * ※ こ?タグは、Transaction タグの対象です?
057     *
058     * @og.formSample
059     * ●形式?lt;og:tableFilter classId="…" />
060     * ●body?あ?EVAL_BODY_BUFFERED:BODYを評価し?{@XXXX} を解析しま?
061     *
062     * ●Tag定義??
063     *   <og:tableFilter
064     *       classId          ○?TAG】データベ?ス処?実行するクラスパスを指定しま???)?
065     *       tableId            【TAG?通常は使?せん)DBTableModel sessionに登録されて?キーを指定しま?
066     *       modifyType         【TAG】データ処??方?A:追?C:更新 D:削除)を指定しま?
067     *       keys               【TAG】リンク先に渡すキーを指定しま?
068     *       vals               【TAG】keys属?に対応する?をCSV形式で??しま?
069     *       selectedAll        【TAG】データを?件選択済みとして処?るかど?[true/false]を指定しま?初期値:false)
070     *       scope              【TAG】キャ?ュする場合?スコープ[request/page/session/applicaton]を指定しま?初期値:session)
071     *       dbid               【TAG?通常は使?せん)Queryオブジェクトを作?する時?DB接続IDを指定しま?
072     *       debug              【TAG】デバッグ??を?力するかど?[true/false]を指定しま?初期値:false)
073     *   >   ... Body ...
074     *   </og:tableFilter>
075     *
076     * ●使用?
077     *    ・引数/プロシジャーを直接書く??
078     *    【entry.jsp?
079     *        <og:tableFilter
080     *            classId     = "WL_LOGICSET"         :TableFilter のサブクラス(実行クラス)
081     *            tableId     = "WL0000"              :登録??DBTableModelのsession/request変数??取得キー
082     *            keys        = "AA,BB,CC"            :実行クラスへの引数のキー
083     *            vals        = "{@AA},{@BB},{@CC}"   :実行クラスへの引数の値
084     *            selectedAll = "false/true"          :処?象の行を全行選択するかど?(初期値:false)
085     *            modifyType  = "A/C/D"               :処??方?A:追?C:更新 D:削除)を指定します?初期値は自動です?
086     *        />
087     *
088     *    ・BODY部?、CSS形式?パラメータ??eys,vals?を記述する?
089     *
090     *        <og:tableFilter
091     *            classId     = "WL_LOGICSET"         :TableFilter のサブクラス(実行クラス)
092     *            tableId     = "WL0000"              :登録??DBTableModelのsession/request変数??取得キー
093     *            selectedAll = "false/true"          :処?象の行を全行選択するかど?(初期値:false)
094     *            modifyType  = "A/C/D"               :処??方?A:追?C:更新 D:削除)を指定します?初期値は自動です?
095     *        >
096     *               {
097     *                   AA    :  {@AA}
098     *                   BB    :  {@BB}
099     *                   CC    :  {@CC}
100     *               }
101     *        </og:tableFilter>
102     *
103     * @og.group そ??
104     * @og.rev 3.8.5.0 (2006/03/20) 新規作?
105     *
106     * @version  0.9.0  2000/10/17
107     * @author   Kazuhiko Hasegawa
108     * @since    JDK1.1,
109     */
110    public class TableFilterTag extends CommonTagSupport {
111            //* こ?プログラ??VERSION??を設定します?       {@value} */
112            private static final String VERSION = "5.6.5.2 (2013/06/21)" ;
113    
114            private static final long serialVersionUID = 565220130621L ;
115    
116            private static final String errMsgId    = HybsSystem.ERR_MSG_KEY;
117            private transient DBTableModel  table   = null;
118    
119            private String          tableId         = HybsSystem.TBL_MDL_KEY;
120            private String          classId         = null;
121            private String          modifyType      = null;
122            private String[]        keys            = null;
123            private String[]        vals            = null;
124    
125            private   String        dbid            = null ; // 4.2.4.0 (2008/06/23)
126    //      private   String        body            = null ; // 4.2.4.0 (2008/06/23) ?.6.5.2 (2013/06/21) sql と paramMap に?るため?ローカル?
127            private   String        sql                     = null ; // 5.6.5.2 (2013/06/21) bodyからSQL??みを?り?す?
128            private   Map<String,String>  paramMap = null;    // 5.6.5.2 (2013/06/21) bodyからparamMapを取りだし?
129    
130            private boolean         selectedAll     = false;
131    
132            /**
133             * Taglibの開始タグが見つかったときに処??doStartTag() ?オーバ?ライドします?
134             *
135             * @return      後続????( EVAL_BODY_BUFFERED )
136             */
137            @Override
138            public int doStartTag() {
139                    table = (DBTableModel)getObject( tableId );
140    
141                    if( keys != null && vals != null && ( keys.length != vals.length ) ) {
142                            String errMsg = "keys と vals の設定?の数が異なります?: " + HybsSystem.CR
143                                                    + "keys.length=[" + keys.length + "] , "
144                                                    + "keys.length=[" + StringUtil.array2line( keys,"," ) + "]"
145                                                    + HybsSystem.CR
146                                                    + "vals.length=[" + vals.length + "] , "
147                                                    + "vals.length=[" + StringUtil.array2line( vals,"," ) + "]";
148                            throw new HybsSystemException( errMsg );
149                    }
150    
151                    startQueryTransaction( tableId );
152    //              return(SKIP_BODY);                              // Body を評価しな?
153                    return ( EVAL_BODY_BUFFERED );  // Body を評価する
154            }
155    
156            /**
157             * Taglibのタグ本体を処??doAfterBody() ?オーバ?ライドします?
158             *
159             * @og.rev 5.6.5.2 (2013/06/21) bodyローカル化?sql、paramMap 追?
160             *
161             * @return      後続????(SKIP_BODY)
162             */
163            @Override
164            public int doAfterBody() {
165    //              body = nval( getBodyString(),body );
166                    String body = nval( getBodyString(),null );
167    
168                    // paramMapの取り出?
169                    paramMap = StringUtil.cssParse( body );
170    
171                    // SQL???出?classId="DBSELECT" の場合?みの処?
172                    if( "DBSELECT".equalsIgnoreCase( classId ) && body != null ) {
173                            int ad1 = body.indexOf( '{' );
174                            int ad2 = body.indexOf( '}' );
175    
176                            if( ad1 >= 0 && ad2 >= 0 ) {
177                                    sql = body.substring( 0,ad1 ).trim() + body.substring( ad2+1 ).trim();
178                            }
179                            else {
180                                    sql = body.trim();
181                            }
182                    }
183    
184                    return(SKIP_BODY);
185            }
186    
187            /**
188             * Taglibの終?グが見つかったときに処??doEndTag() ?オーバ?ライドします?
189             *
190             * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設?
191             * @og.rev 4.2.3.0 (2008/06/23) DBIDとボディー部??記述を下位クラスに渡す用に修正
192             * @og.rev 4.3.7.4 (2009/07/01) Resouceオブジェクトを下位クラスに渡す用に修正
193             * @og.rev 5.1.9.0 (2010/08/01) Transaction 対?
194             * @og.rev 5.2.1.0 (2010/10/01) debugPrint() メソ?の処?件見直?
195             * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更 、Transaction対応で、close処?入れる?
196             * @og.rev 5.6.5.2 (2013/06/21) bodyローカル化?sql、paramMap 追?
197             *
198             * @return      後続????
199             */
200            @Override
201            public int doEndTag() {
202                    // ??時には、オブジェクト?部??を表示する?
203    //              if( isDebug() ) {
204    //                      debugPrint();   // 5.2.1.0 (2010/10/01) debugPrint() メソ?自体に、isDebug() が?込まれて??
205    //              }
206                    debugPrint();   // 5.2.1.0 (2010/10/01) debugPrint() メソ?自体に、isDebug() が?込まれて??
207                    int rtnCode = EVAL_PAGE;        // try ??finally の関係で、変数化しておく
208    
209                    int[] rowNo = getParameterRows();
210    
211                    // 5.1.9.0 (2010/08/01) Transaction 対?
212    //              final Transaction tran ;
213                    Transaction tran = null;
214                    final TableFilter filter ;
215                    // 5.3.7.0 (2011/07/01) Transaction対応で、close処?入れる?
216                    try {
217                            TransactionTag tranTag = (TransactionTag)findAncestorWithClass( this,TransactionTag.class );
218                            if( tranTag == null ) {
219            //                      tran = new TransactionReal( dbid,getApplicationInfo() );
220                                    tran = new TransactionReal( getApplicationInfo() );             // 5.3.7.0 (2011/07/01) 引数変更
221                            }
222                            else {
223                                    tran = tranTag.getTransaction();
224                            }
225    
226                            String cls = HybsSystem.sys( "TableFilter_" + classId );
227    //                      TableFilter filter = (TableFilter)HybsSystem.newInstance( cls );
228                            filter = (TableFilter)HybsSystem.newInstance( cls );
229    
230                            filter.setDBTableModel( table );
231                            filter.setParameterRows( rowNo );
232                            filter.setModifyType( modifyType );
233                            filter.setKeysVals( keys,vals );
234            //              filter.setApplicationInfo( getApplicationInfo() );      // 3.8.7.0 (2006/12/15)
235                            filter.setTransaction( tran );                                          // 5.1.9.0 (2010/08/01) Transaction 対?
236                            filter.setDebug( isDebug() );
237                            filter.setDbid( dbid );                                 // 4.2.4.0 (2008/06/23)
238    //                      filter.setSql( body );                                  // 4.2.4.0 (2008/06/23)?.6.5.2 (2013/06/21) body?
239                            filter.setSql( sql );                                   // 5.6.5.2 (2013/06/21) sql 追?
240                            filter.setParamMap( paramMap );                 // 5.6.5.2 (2013/06/21) paramMap 追?
241                            filter.setResource( getResource() );    // 4.3.7.4 (2009/07/01)
242    
243                            table = filter.execute();
244    
245                            int errCode = filter.getErrorCode();
246                            ErrorMessage errMessage = filter.getErrorMessage();
247    
248                            if( errCode >= ErrorMessage.NG )  {  // 異常
249                                    rtnCode = SKIP_PAGE;
250                            }
251    
252                            String err = TaglibUtil.makeHTMLErrorTable( errMessage,getResource() );
253                            if( err != null && err.length() > 0 ) {
254                                    jspPrint( err );
255                                    setSessionAttribute( errMsgId,errMessage );
256                            }
257                            else {
258                                    removeSessionAttribute( errMsgId );
259                            }
260                    }
261                    finally {
262                            if( tran != null ) { tran.close(); }
263                    }
264    
265                    if( table != null && ! commitTableObject( tableId, table ) ) {
266                            return (SKIP_PAGE);
267                    }
268    
269    //              if( errCode >= ErrorMessage.NG )  {  // 異常
270    //                      return(SKIP_PAGE);
271    //              }
272    //              else {
273    //                      return(EVAL_PAGE);
274    //              }
275    
276                    return( rtnCode );
277            }
278    
279            /**
280             * タグリブオブジェクトをリリースします?
281             * キャ?ュされて再利用される?で、フィールド?初期設定を行います?
282             *
283             * @og.rev 5.6.5.2 (2013/06/21) body?、sql、paramMap 追?
284             */
285            @Override
286            protected void release2() {
287                    super.release2();
288                    table           = null;
289                    tableId         = HybsSystem.TBL_MDL_KEY;
290                    classId         = null;
291                    modifyType      = null;
292                    keys            = null;
293                    vals            = null;
294                    selectedAll     = false;
295                    dbid            = null; // 4.2.4.0 (2008/06/23)
296    //              body            = null; // 4.2.4.0 (2008/06/23)?.6.5.2 (2013/06/21) sql と paramMap に?るため?ローカル?
297                    sql                     = null; // 5.6.5.2 (2013/06/21) bodyからSQL??みを?り?す?
298                    paramMap        = null; // 5.6.5.2 (2013/06/21) bodyからparamMapを取りだす?
299            }
300    
301            /**
302             * 表示??タの HybsSystem.ROW_SEL_KEY を?に?ばれた 行を処??対象とします?
303             *
304             * @return      選択行?配?
305             */
306            @Override
307            protected int[] getParameterRows() {
308                    final int[] rowNo ;
309                    if( selectedAll ) {
310                            int rowCnt = table.getRowCount();
311                            rowNo = new int[ rowCnt ];
312                            for( int i=0; i<rowCnt; i++ ) {
313                                    rowNo[i] = i;
314                            }
315                    } else {
316                            rowNo = super.getParameterRows();               // 4.0.0 (2005/01/31)
317                    }
318                    return rowNo;
319            }
320    
321            /**
322             * 【TAG】データベ?ス処?実行するクラスパスを指定します?
323             *
324             * @og.tag
325             * ここで?するクラスIDは、シス?リソース にて TableFilter の
326             * サブクラス(インターフェース継承)として?する?があります?
327             *
328             * クラス自身は、org.opengion.hayabusa.db.TableFilter インターフェースを継承して??があります?
329             * {@og.doc03Link tableFilter TableFilter_**** クラス}
330             *
331             * @param       id TableFilter インターフェースを継承して?実クラスの ID
332             * @see         org.opengion.hayabusa.db.TableFilter  TableFilter インターフェース
333             */
334            public void setClassId( final String id ) {
335                    classId = nval( getRequestParameter( id ),classId );
336            }
337    
338            /**
339             * 【TAG?通常は使?せん)結果のDBTableModelを?sessionに登録するとき?キーを指定しま?
340             *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])?
341             *
342             * @og.tag
343             * 検索結果より、DBTableModelオブジェクトを作?します?これを?下流?viewタグ等に
344             * 渡す?合に??常は、session を利用します?そ?場合?登録キーです?
345             * query タグを同時に実行して、結果を求める?合?同?モリに配置される為?
346             * こ? tableId 属?を利用して、メモリ空間を?ます?
347             *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])?
348             *
349             * @param       id sessionに登録する時? ID
350             */
351            public void setTableId( final String id ) {
352                    tableId = nval( getRequestParameter( id ),tableId );
353            }
354    
355            /**
356             * 【TAG】データを?件選択済みとして処?るかど?[true/false]を指定しま?初期値:false)?
357             *
358             * @og.tag
359             * 全ての??タを選択済み??タとして扱って処?ます?
360             * 全件処?る?合に、指定します?(true/false)
361             * ?ォル?false です?
362             *
363             * @param  all ??タを?件選択済み [true:全件選択済み/false:通常]
364             */
365            public void setSelectedAll( final String all ) {
366                    selectedAll = nval( getRequestParameter( all ),selectedAll );
367            }
368    
369            /**
370             * 【TAG】データ処??方?A:追?C:更新 D:削除)を指定します?
371             *
372             * @og.tag
373             * 通常は、DBTableModel に自動設定されて? modifyType を?に、データ処?法を
374             * 選別します?(A:追?C:更新 D:削除)
375             * こ?場合?行単位で modifyType の値を取得して判別する?がありますが、?には
376             * 処?象は、?件おな?modifyType である可能性が高いです?
377             * また?selectedAll などで強制?全件処?象とする場合?、modifyType に値?
378             * 設定さて?せん。その様な場合に外部より modifyType を指定します?
379             * 初期値は、?動判?です?
380             *
381             * @param  type ??タ処??方?A:追?C:更新 D:削除)
382             */
383            public void setModifyType( final String type ) {
384                    modifyType = nval( getRequestParameter( type ),modifyType );
385    
386                    if( modifyType != null && !"A".equals( modifyType ) && !"C".equals( modifyType ) && !"D".equals( modifyType ) ) {
387                            String errMsg = "modifyType は A:追?C:更新 D:削除 のどれかを指定してください? " + HybsSystem.CR
388                                                    + "modifyType=[" + modifyType + "]";
389                            throw new HybsSystemException( errMsg );
390                    }
391            }
392    
393            /**
394             * 【TAG】リンク先に渡すキーを指定します?
395             *
396             * @og.tag
397             * 戻る時に、検索時?キャ?ュに?した引数以外に?したり、別の値に置き換えた?
398             * する場合?キーを設定できます?カンマ区?で??できます?
399             * vals 属?には、キーに対応する?を?設定してください?
400             * ?方法?、CSV変数を?に?してから、getRequestParameter で値を取得します?
401             * こうしな???タ自身にカンマを持って?場合に?をミスる為です?
402             *
403             * @param       key リンク先に渡すキー
404             */
405            public void setKeys( final String key ) {
406                    keys = getCSVParameter( key );
407            }
408    
409            /**
410             * 【TAG】names属?に対応する?をCSV形式で??します?
411             *
412             * @og.tag
413             * キーに設定した?を?カンマ区??で?して出来ます?
414             * ??序?、キーと同じにしておいて下さ??
415             * ?方法?、CSV変数を?に?してから、getRequestParameter で値を取得します?
416             * こうしな???タ自身にカンマを持って?場合に?をミスる為です?
417             *
418             * @param       val names属?に対応する?
419             */
420            public void setVals( final String val ) {
421                    vals = getCSVParameter( val );
422            }
423    
424            /**
425             * 【TAG?通常は使?せん)Queryオブジェクトを作?する時?DB接続IDを指定します?
426             *
427             * @og.tag
428             * Queryオブジェクトを作?する時?DB接続IDを指定します?
429             * これは、シス?リソースで、DEFAULT_DB_URL 等で?して? ??タベ?ス接続?
430             * ??に、XX_DB_URL を定義することで?dbid="XX" とすると、この 接続?を使用して
431             * ??タベ?スにアクセスできます?
432             *
433             * @param       id ??タベ?ス接続ID
434             */
435            public void setDbid( final String id ) {
436                    dbid = nval( getRequestParameter( id ),dbid );
437            }
438    
439            /**
440             * シリアライズ用のカスタ?リアライズ書き込みメソ?
441             *
442             * @og.rev 4.0.0.0 (2006/09/31) 新規追?
443             * @serialData ?のオブジェクト?、シリアライズされません?
444             *
445             * @param       strm    ObjectOutputStreamオブジェク?
446             * @throws IOException  入出力エラーが発生した??
447             */
448            private void writeObject( final ObjectOutputStream strm ) throws IOException {
449                    strm.defaultWriteObject();
450            }
451    
452            /**
453             * シリアライズ用のカスタ?リアライズ読み込みメソ?
454             *
455             * ここでは、transient 宣?れた?変数の??初期化が?なフィールド?み設定します?
456             *
457             * @og.rev 4.0.0.0 (2006/09/31) 新規追?
458             * @serialData ?のオブジェクト?、シリアライズされません?
459             *
460             * @param       strm    ObjectInputStreamオブジェク?
461             * @see #release2()
462             * @throws IOException  シリアライズに関する入出力エラーが発生した??
463             * @throws ClassNotFoundException       クラスを見つけることができなかった??
464             */
465            private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
466                    strm.defaultReadObject();
467            }
468    
469            /**
470             * こ?オブジェクト???表現を返します?
471             * 基本???目?使用します?
472             *
473             * @return こ?クラスの??表現
474             */
475            @Override
476            public String toString() {
477                    return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
478                                    .println( "VERSION"                     ,VERSION                )
479                                    .println( "tableId"                     ,tableId                )
480                                    .println( "classId"                     ,classId                )
481                                    .println( "modifyType"          ,modifyType             )
482                                    .println( "selectedAll"         ,selectedAll    )
483                                    .println( "keys"                        ,keys                   )
484                                    .println( "vals"                        ,vals                   )
485                                    .println( "dbid"                        ,dbid                   ) // 4.2.4.0 (2008/06/23)
486    //                              .println( "body"                        ,body                   ) // 4.2.4.0 (2008/06/23)
487                                    .println( "sql"                         ,sql                    ) // 5.6.5.2 (2013/06/21)
488                                    .fixForm().toString() ;
489            }
490    }