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.plugin.table; 017 018import org.opengion.fukurou.db.DBUtil; 019import org.opengion.fukurou.db.Transaction; // 5.5.2.6 (2012/05/25) 020import org.opengion.fukurou.model.Formatter; 021import org.opengion.fukurou.util.ErrorMessage; 022import org.opengion.fukurou.util.StringUtil; 023import org.opengion.hayabusa.db.AbstractTableFilter; 024import org.opengion.hayabusa.db.DBTableModel; 025 026import java.util.Map; 027 028/** 029 * TableFilter_DBSELECT は、TableFilter インターフェースを継承した、DBTableModel 処理用の 030 * 実装クラスです。 031 * 032 * ここでは、Body部にかかれたSQLを実行した結果を、テーブルモデルにセットします。 033 * SQL文から取得されるカラム名とテーブルモデルのカラム名は一致している必要があります。 034 * 検索結果のカラムがテーブルモデルに存在していない場合はエラーとなります。 035 * 以下の属性を指定しないと、データが存在しない場合はNULLがセットされます。 036 * また、2行以上検索された場合でも、1行目のデータのみをセットします。 037 * 038 * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか、BODY 部にCSS形式で記述します。 039 * ただし、このフィルターは、BODY部に、SQL文も記述する為、注意が必要です。 040 * ルール的には、一番最初に見つけた "{" と、"}" の間の文字列がパラメータと認識します。 041 * よって、SQL文を記述する場合は、このパラメータの後ろに記述するか、keys,vals を利用ください。 042 * 【パラメータ】 043 * { 044 * INNER_JOIN : データが存在しない場合、テーブルの該当行を削除します。(初期値:false) 045 * APPEND : 2行以上検索された場合、データをアペンドします。 (初期値:false) 046 * SEPARATOR : APPENDする場合の区切り文字を指定します。 (初期値:" "スペース) 047 * } 048 * 049 * Body部にかかれたSQLには[XXXX]形式の変数が指定できます。 050 * 051 * @og.formSample 052 * ●形式: 053 * @ <og:tableFilter classId="DBSELECT" > 054 * 055 * </og:tableFilter> 056 * 057 * A <og:tableFilter classId="DBSELECT" > 058 * { 059 * INNER_JOIN : true ; 060 * } 061 * select AAA,BBB,CCC from XXX 062 * </og:tableFilter> 063 * 064 * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを追加 065 * 066 * @version 0.9.0 2000/10/17 067 * @author Hiroki Nakamura 068 * @since JDK1.1, 069 */ 070public class TableFilter_DBSELECT extends AbstractTableFilter { 071 //* このプログラムのVERSION文字列を設定します。 {@value} */ 072 private static final String VERSION = "5.6.6.1 (2013/07/12)" ; 073 074 /** 075 * keys の整合性チェックを行うための初期設定を行います。 076 * 077 * @og.rev 5.6.6.1 (2013/07/12) keys の整合性チェック対応 078 * 079 * @param keysMap keys の整合性チェックを行うための Map 080 */ 081 @Override 082 protected void init( final Map<String,String> keysMap ) { 083 keysMap.put( "INNER_JOIN" , "データが存在しない場合、テーブルの該当行を削除します(初期値:false)" ); 084 keysMap.put( "APPEND" , "2行以上検索された場合、データをアペンドします (初期値:false)" ); 085 keysMap.put( "SEPARATOR" , "APPENDする場合の区切り文字を指定します (初期値:\" \"スペース)" ); 086 } 087 088 private DBTableModel table = null; // 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 089 090 /** 091 * DBTableModel処理を実行します。 092 * 093 * @og.rev 4.3.7.0 (2009/06/01) 実装大幅変更 094 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応 095 * @og.rev 5.5.2.6 (2012/05/25) protected変数を、private化したため、getterメソッドで取得するように変更 096 * 097 * @return 処理結果のDBTableModel 098 */ 099 public DBTableModel execute() { 100 table = getDBTableModel(); // 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 101 102 boolean innerJoin = StringUtil.nval( getValue("INNER_JOIN"), false ); 103 boolean isAppend = StringUtil.nval( getValue("APPEND"), false ); 104 String separator = StringUtil.nval( getValue("SEPARATOR"), " " ); 105 106 Formatter format = new Formatter( table ); 107// format.setFormat( sql ); 108 format.setFormat( getSql() ); // 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 109 int[] sqlClmNo = format.getClmNos(); 110 String query = format.getQueryFormatString(); 111 112 String[] data = null; 113 String[] param = null; 114 int[] clmNo = null; 115 Transaction tran = getTransaction(); // 5.5.2.6 (2012/05/25) 116 String dbid = getDbid(); // 5.5.2.6 (2012/05/25) 117 int[] rowNo = getParameterRows(); // 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 118 int rowCount = rowNo.length; 119 for ( int row = rowCount - 1; row >= 0; row-- ) { 120 try { 121 param = getTableModelData( rowNo[row], sqlClmNo ); 122 123 final String[][] dbData; 124 if ( row == rowCount - 1 ) { 125// String[][] rtn = DBUtil.dbExecute( query, param, appInfo, dbid, true ); 126 String[][] rtn = DBUtil.dbExecute( query, param, tran, dbid, true ); // 5.1.9.0 (2010/08/01) Transaction 対応 127 clmNo = getTableColumnNo( rtn[0] ); 128 dbData = new String[rtn.length - 1][rtn[0].length]; 129 System.arraycopy( rtn, 1, dbData, 0, dbData.length ); 130 } 131 else { 132// dbData = DBUtil.dbExecute( query, param, appInfo, dbid, false ); 133 dbData = DBUtil.dbExecute( query, param, tran, dbid, false ); // 5.1.9.0 (2010/08/01) Transaction 対応 134 } 135 136 data = table.getValues( rowNo[row] ); 137 if ( dbData != null && dbData.length > 0 && dbData[0] != null && dbData[0].length > 0 ) { 138 for ( int i = 0; i < clmNo.length; i++ ) { 139 if( isAppend ) { 140 StringBuilder buf = new StringBuilder(); 141 for( int j = 0; j < dbData.length; j++ ) { 142 if( j > 0 ) { 143 buf.append( separator ); 144 } 145 buf.append( dbData[j][i] ); 146 } 147 data[clmNo[i]] = buf.toString(); 148 } 149 else { 150 data[clmNo[i]] = dbData[0][i]; // 副作用を及ぼしています。注意 151 } 152 } 153 } 154 else if( innerJoin ) { 155 table.removeValue(rowNo[row]); 156 } 157 } 158 catch ( RuntimeException ex ) { 159 ErrorMessage errMessage = makeErrorMessage( "TableFilter_DBSELECT Error", ErrorMessage.NG ); 160 errMessage.addMessage( rowNo[row] + 1, ErrorMessage.NG, ex.getMessage() ); 161 errMessage.addMessage( rowNo[row] + 1, ErrorMessage.NG, StringUtil.array2csv( data ) ); 162// errMessage.addMessage( rowNo[row] + 1, ErrorMessage.NG, "SQL=[" + sql + "]" ); 163 errMessage.addMessage( rowNo[row] + 1, ErrorMessage.NG, "SQL=[" + getSql() + "]" ); 164 errMessage.addMessage( rowNo[row] + 1, ErrorMessage.NG, StringUtil.array2csv( param ) ); 165 } 166 } 167 168 return table; 169 } 170 171 /** 172 * 指定の行番号の、カラムNo配列(int[])に対応した値の配列を返します。 173 * 174 * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を 175 * 処理の対象とします。 176 * 177 * @param row 行番号 178 * @param clmNo カラムNo配列 179 * 180 * @return 行番号とカラムNo配列に対応した、値の配列 181 */ 182 private String[] getTableModelData( final int row, final int[] clmNo ) { 183 String[] values = new String[clmNo.length]; 184 for( int i = 0; i < values.length; i++ ) { 185 values[i] = table.getValue( row, clmNo[i] ); 186 } 187 return values; 188 } 189}