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.db.Query;
022import org.opengion.hayabusa.resource.GUIInfo;
023
024import org.opengion.fukurou.util.StringUtil ;
025import static org.opengion.fukurou.util.StringUtil.nval ;
026
027/**
028 * 【廃止】SQL文を直接指定して、データベースに追加/更新/削除を行います(queryType="JDBCPrepared")。
029 *
030 * 存在チェックを行う場合は、tableExist タグと併用してください。
031 * 複雑な処理が必要な場合は、従来より使用しています、PLSQLをCALLする、
032 * plsqlUpdateタグを使用してください。
033 *
034 * ※ このタグは、Transaction タグの対象です。
035 *
036 * @og.formSample
037 * ●形式:<og:update command="…" names="…" queryType="JDBCPrepared" >
038 *             {@SQL}
039 *         </og:update>
040 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します)
041 *
042 * ●Tag定義:
043 *   <og:update
044 *       queryType          【廃止】Query を発行する為のクラスIDを指定します(初期値:JDBCPrepared)
045 *       command            【TAG】コマンド(NEW,RENEW)をセットします(PlsqlUpdateTag,UpdateTag の場合は、ENTRY)
046 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session)
047 *       displayMsg         【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します (初期値:VIEW_DISPLAY_MSG[=])
048 *       names              【TAG】PL/SQLを利用する場合の引数にセットすべき データの名称をCSV形式で複数指定します
049 *       quotCheck          【TAG】リクエスト情報の クォーティション(') 存在チェックを実施するかどうか[true/false]を設定します(初期値:USE_SQL_INJECTION_CHECK)
050 *       tableId            【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
051 *       dbid               【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します
052 *       xssCheck           【TAG】リクエスト情報の HTMLTag開始/終了文字(><) 存在チェックを実施するかどうか[true/false]を設定します (初期値:USE_XSS_CHECK[=true])
053 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
054 *   >   ... Body ...
055 *   </og:update>
056 *
057 * ●使用例
058 *    ・引数/プロシジャーを他のJSPから渡す場合
059 *    【copy.jsp】
060 *        <og:value scope="session" key="names" value="CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG" />
061 *        <og:value scope="session" key="SQL" >
062 *          INSERT INTO GE41
063 *               (CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG,
064 *               FGJ,DYSET,DYUPD,USRSET,USRUPD,PGUPD)
065 *          VALUES
066 *               (?,?,?,?,?,?,
067 *               '1','{@USER.YMDH}','{@USER.YMDH}','{@USER.ID}','{@USER.ID}','{@GUI.KEY}')
068 *        </og:value>
069 *
070 *    【entry.jsp】
071 *        <og:update
072 *            command   = "{@command}"
073 *            queryType = "JDBCPrepared"
074 *            names     = "{@names}"  >
075 *        {@SQL}
076 *        </og:update>
077 *
078 *        <!-- 前画面で指定のSQL文を削除します。(scope="session"なので削除が必要。) -->
079 *        <og:value scope="session" key="names" command="REMOVE" />
080 *        <og:value scope="session" key="SQL"   command="REMOVE" />
081 *
082 *    ・引数/プロシジャーを直接書く場合
083 *    【entry.jsp】
084 *        <og:update
085 *            command   = "{@command}"
086 *            queryType = "JDBCPrepared"
087 *            names     = "CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG"
088 *        >
089 *            INSERT INTO GE41
090 *                (CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG,
091 *                 FGJ,DYSET,DYUPD,USRSET,USRUPD,PGUPD)
092 *            VALUES
093 *                (?,?,?,?,?,?,
094 *                 '1','{@USER.YMDH}','{@USER.YMDH}','{@USER.ID}','{@USER.ID}','{@GUI.KEY}')
095 *        </og:update>
096 *
097 * @og.rev 4.0.0.0 (2005/01/31) 廃止
098 * @og.group (廃止)DB登録
099 *
100 * @deprecated 4.0.0 (2005/01/31) 廃止。tableUpdate を利用するようにしてください。
101 * @version  4.0
102 * @author   Kazuhiko Hasegawa
103 * @since    JDK5.0,
104 */
105@Deprecated public class UpdateTag extends QueryTag {
106        //* このプログラムのVERSION文字列を設定します。   {@value} */
107        private static final String VERSION = "4.0.0.0 (2005/01/31)" ;
108
109        private static final long serialVersionUID = 400020050131L ;
110
111        /** command 引数に渡す事の出来る コマンド  登録{@value} */
112        public static final String CMD_ENTRY  = "ENTRY" ;
113        /** command 引数に渡す事の出来る コマンド リスト  */
114        private static final String COMMAND_LIST = CMD_ENTRY;
115
116        /**
117         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
118         *
119         * @return      後続処理の指示
120         */
121        @Override
122        public int doStartTag() {
123                dyStart = System.currentTimeMillis();
124
125                table = (DBTableModel)getObject( tableId );
126                if( table == null || table.getRowCount() == 0 ||
127                        ! check( command, COMMAND_LIST ) ) { return(SKIP_BODY); }
128                return( EVAL_BODY_BUFFERED );   // Body を評価する。( extends BodyTagSupport 時)
129        }
130
131        /**
132         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
133         *
134         * @og.rev 3.5.5.8 (2004/05/20) ErrorMessage オブジェクトを、正常終了時、クリア
135         *
136         * @return      後続処理の指示
137         */
138        @Override
139        public int doEndTag() {
140                debugPrint();           // 4.0.0 (2005/02/28)
141
142                if( check( command, COMMAND_LIST ) ) {
143                        removeSessionAttribute( errMsgId );
144                }
145
146                executeCount = getParameterRows().length ;              // チェック行の数が登録件数と仮定
147
148                // 4.0.0 (2005/01/31) 処理時間集計
149                long dyTime = System.currentTimeMillis()-dyStart;
150
151                // 4.0.0 (2005/01/31) セキュリティチェック(データアクセス件数登録)
152                GUIInfo guiInfo = (GUIInfo)getSessionAttribute( HybsSystem.GUIINFO_KEY );
153                if( guiInfo != null ) { guiInfo.addWriteCount( executeCount,dyTime,sql ); }
154
155                return(EVAL_PAGE);
156        }
157
158        /**
159         * Query を実行します。
160         *
161         * @og.rev 2.1.2.3 (2002/12/02) データベース更新時に、更新フラグをセットするように変更
162         * @og.rev 3.4.0.0 (2003/09/01) 登録エラー時のキーと値を表示するように変更。
163         * @og.rev 3.5.0.0 (2003/09/17) カラム名ではなく、カラム番号を先に求めておく方式に変更。
164         * @og.rev 3.5.6.0 (2004/06/18) DBRowHeader のパッケージプライベート化に伴なう変更
165         * @og.rev 4.0.0.0 (2005/01/31) getParameterRows() を使用するように変更
166         *
167         * @param   query オブジェクト
168         */
169        @Override
170        protected void execute( final Query query ) {
171                // long st = System.currentTimeMillis();
172                String[] values    = null;
173                int row = 0;
174                try {
175                        if( names == null ) {
176                                query.execute( null );
177                        }
178                        else {
179                                int[] rowNo = getParameterRows();               // 4.0.0 (2005/01/31)
180                                if( rowNo.length > 0 ) {
181                                        int[] clmNo = getTableColumnNo( StringUtil.csv2Array( names ) );
182                                        values    = null;
183                                        // 逆順にDELETEしないと、行番号がずれてしまう。
184                                        for( int j=rowNo.length-1; j>=0; j-- ) {
185                                                row = rowNo[j];
186                                                values = getTableModelData( clmNo,row );        // 3.5.0.0
187                                                query.execute( values );
188                                                if( DBTableModel.DELETE_TYPE.equals( table.getModifyType( row ) ) ) {
189                                                        table.removeValue( row );
190                                                }
191                                                else {
192                                                        table.resetModify( row );
193                                                }
194                                        }
195                                }
196                        }
197//                      if( query.getUpdateFlag() ) { query.commit(); }
198                        if( query.isUpdate() ) { query.commit(); }
199                }
200                catch( HybsSystemException ex ) {
201                        query.rollback();
202        // 3.4.0.0 (2003/09/01) 登録エラー時のキーと値を表示するように変更。
203                        String errMsg = "DATABASE ERROR! "
204                                + "rowNo=[" + ( row ) + "] " + HybsSystem.CR
205                                + "nameArray=[" + names + "]" + HybsSystem.CR
206                                + "values=[" + StringUtil.array2csv( values ) + "]" + HybsSystem.CR ;
207                        throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び順変更
208                }
209                finally {
210                        if( query != null ) { query.close(); }
211                }
212                // System.out.println( ( System.currentTimeMillis() - st ) + " ms" );
213        }
214
215        /**
216         *  カラム名配列(String[])より、対応するカラムNo配列(int[])を作成します。
217         *
218         * @og.rev 3.5.0.0 (2003/09/17) 新規追加
219         *
220         * @param       nameArray カラム名配列
221         *
222         * @return      カラムNo配列
223         */
224        private int[] getTableColumnNo( final String[] nameArray ) {
225                int[] clmNo = new int[ nameArray.length ];
226                for( int i=0; i<clmNo.length; i++ ) {
227                        clmNo[i] = table.getColumnNo( nameArray[i] );
228                }
229                return clmNo;
230        }
231
232        /**
233         *  指定の行番号の、カラムNo配列(int[])に対応した値の配列を返します。
234         *
235         * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を
236         * 処理の対象とします。
237         *
238         * @og.rev 3.5.0.0 (2003/09/17) カラム名ではなく、カラム番号を受け取るように修正。
239         *
240         * @param       clmNo   カラムNo配列
241         * @param       row             行番号
242         *
243         * @return      行番号とカラムNo配列に対応した、値の配列
244         */
245        private String[] getTableModelData( final int[] clmNo,final int row ) {
246                String[] values = new String[ clmNo.length ];
247                for( int i=0; i<values.length; i++ ) {
248                        values[i] = table.getValue( row,clmNo[i] ) ;
249                }
250                return values;
251        }
252
253        /**
254         * 【廃止】Query を発行する為のクラスIDを指定します({@og.doc03Link queryType 初期値:JDBCPrepared})。
255         *
256         * @og.tag
257         * 登録を実行する手段は、Query インターフェースの実装クラスになります。
258         * このタグでは、Query.execute( String[] ) メソッドが複数回呼ばれます。
259         * これは、DBTableModelの選択された行に対して、繰り返し呼ばれます。
260         *
261         * 通常、このタグを使用する場合は、queryType="JDBCPrepared" を指定します。
262         *
263         * タグにより使用できる/出来ないがありますが、これは、org.opengion.hayabusa.db
264         * 以下の Query_**** クラスの **** を与えます。
265         * これらは、Query インターフェースを継承したサブクラスです。
266         * {@og.doc03Link queryType Query_**** クラス}
267         *
268         * @og.rev 3.5.4.2 (2003/12/15) JavaDocコメント用にメソッド追加。
269         *
270         * @param       id Query を発行する為の実クラス ID
271         * @see         org.opengion.hayabusa.db.Query  Queryのサブクラス
272         * @see         org.opengion.hayabusa.db.Query#execute( String[] )
273         * @deprecated クラスが廃止
274         */
275        @Deprecated public void setQueryType( final String id ) {
276                super.setQueryType( nval( id,"JDBCPrepared" ) );
277        }
278}