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.io;
017
018 import org.opengion.fukurou.util.Closer ;
019 import org.opengion.fukurou.util.LogWriter;
020
021 import java.sql.Connection;
022 import java.sql.Date;
023 import java.sql.Timestamp;
024 import java.sql.ResultSet;
025 import java.sql.ResultSetMetaData;
026 import java.sql.SQLException;
027 import java.sql.Statement;
028 import java.sql.Types;
029
030 import java.util.List;
031 import java.util.ArrayList;
032
033 import org.jfree.data.jdbc.JDBCCategoryDataset;
034 import org.jfree.data.Range;
035
036 /**
037 * HybsJDBCCategoryDataset は、org.jfree.data.jdbc.JDBCCategoryDataset を継承したサブクラスで?
038 * executeQuery(Connection , String ) をオーバ?ライドして?す?
039 * これは、?のソースの??タベ?ス検索結果を?部で持っておき、getValue(int row, int column)
040 * メソ?で直接値を返します?
041 * series の横持ち(標準と同じ) 対応です?
042 * 参?:JFreeChart : a free chart library for the Java(tm) platform(jfreechart-1.0.6)
043 *
044 * @og.rev 3.8.9.2 (2007/07/28) 新規作?
045 *
046 * @version 0.9.0 2001/05/05
047 * @author Kazuhiko Hasegawa
048 * @since JDK1.1,
049 */
050 public class HybsJDBCCategoryDataset2 extends JDBCCategoryDataset {
051 private static final long serialVersionUID = 562120130308L ;
052
053 private Number[][] numdata = null;
054 private Range range = null;
055 private final int hsCode = Long.valueOf( System.nanoTime() ).hashCode() ; // 5.1.9.0 (2010/08/01) equals,hashCode
056
057 // 4.3.5.0 (2009/02/01) ?ブジェクトを特定するため?ユニ?クな番号
058 // private final int uniqNo = Double.valueOf( Math.random() ).hashCode() ; // 5.1.8.0 (2010/07/01) ?
059
060 /**
061 * Creates a new dataset with the given database connection, and executes
062 * the supplied query to populate the dataset.
063 *
064 * @param connection the connection.
065 * @param query the query.
066 *
067 * @throws SQLException if there is a problem executing the query.
068 */
069 public HybsJDBCCategoryDataset2( final Connection connection, final String query ) throws SQLException {
070 super( connection );
071 innerQuery( connection,query );
072 }
073
074 /**
075 * Populates the dataset by executing the supplied query against the
076 * existing database connection. If no connection exists then no action
077 * is taken.
078 *
079 * The results from the query are extracted and cached locally, thus
080 * applying an upper limit on how many rows can be retrieved successfully.
081 *
082 * @og.rev 4.0.0.0 (2007/11/28) new Long(long) ?Long.valueOf(long) 変更
083 * @og.rev 4.0.0.0 (2007/11/28) resultSet,statement ?Closer でclose する?
084 * @og.rev 4.0.0.0 (2007/11/28) Range 求めで nullポインタを参照外しの修正
085 * @og.rev 4.0.0.0 (2007/11/30) public な executeQuery メソ??private 化します?
086 *
087 * @param con the connection.
088 * @param query the query.
089 *
090 * @throws SQLException if there is a problem executing the query.
091 */
092 @Override
093 public void executeQuery( final Connection con, final String query ) throws SQLException {
094 innerQuery( con,query );
095 }
096
097 /**
098 * Populates the dataset by executing the supplied query against the
099 * existing database connection. If no connection exists then no action
100 * is taken.
101 *
102 * The results from the query are extracted and cached locally, thus
103 * applying an upper limit on how many rows can be retrieved successfully.
104 *
105 * @og.rev 4.0.0.0 (2007/11/28) new Long(long) ?Long.valueOf(long) 変更
106 * @og.rev 4.0.0.0 (2007/11/28) resultSet,statement ?Closer でclose する?
107 * @og.rev 4.0.0.0 (2007/11/28) Range 求めで nullポインタを参照外しの修正
108 * @og.rev 5.6.2.1 (2013/03/08) Types.DATE と Types.TIMESTAMP で処??ます?
109 *
110 * @param con the connection.
111 * @param query the query.
112 *
113 * @throws SQLException if there is a problem executing the query.
114 */
115 private void innerQuery( final Connection con, final String query ) throws SQLException {
116
117 Statement statement = null;
118 ResultSet resultSet = null;
119 try {
120 statement = con.createStatement();
121 resultSet = statement.executeQuery(query);
122 ResultSetMetaData metaData = resultSet.getMetaData();
123
124 // Range を予め求めておきます?
125 double minimum = Double.POSITIVE_INFINITY;
126 double maximum = Double.NEGATIVE_INFINITY;
127
128 int columnCount = metaData.getColumnCount();
129 if(columnCount < 2) {
130 String errMsg = "JDBCCategoryDataset.executeQuery() : insufficient columns "
131 + "returned from the database. \n"
132 + " SQL=" + query ;
133 throw new SQLException( errMsg );
134 }
135
136 List<Number[]> rowList = new ArrayList<Number[]>();
137 while (resultSet.next()) {
138 Number[] clmList = new Number[columnCount-1];
139 // first column contains the row key...
140 // Comparable rowKey = resultSet.getString(1);
141 String rowKey = resultSet.getString(1); // 4.3.3.6 (2008/11/15) Generics警告対?
142 for( int column=2; column<=columnCount; column++ ) {
143
144 // Comparable columnKey = metaData.getColumnName(column);
145 String columnKey = metaData.getColumnName(column); // 4.3.3.6 (2008/11/15) Generics警告対?
146 int columnType = metaData.getColumnType(column);
147
148 Number value = null;
149 switch (columnType) {
150 case Types.TINYINT:
151 case Types.SMALLINT:
152 case Types.INTEGER:
153 case Types.BIGINT:
154 case Types.FLOAT:
155 case Types.DOUBLE:
156 case Types.DECIMAL:
157 case Types.NUMERIC:
158 case Types.REAL: {
159 value = (Number)resultSet.getObject(column);
160 break;
161 }
162 case Types.DATE:
163 case Types.TIME: {
164 Date date = (Date) resultSet.getObject(column);
165 value = Long.valueOf(date.getTime());
166 break;
167 }
168 // 5.6.2.1 (2013/03/08) Types.DATE と Types.TIMESTAMP で処??ます?
169 case Types.TIMESTAMP: {
170 Timestamp time = (Timestamp) resultSet.getObject(column);
171 value = Long.valueOf(time.getTime());
172 break;
173 }
174 case Types.CHAR:
175 case Types.VARCHAR:
176 case Types.LONGVARCHAR: {
177 String string = (String)resultSet.getObject(column);
178 try {
179 value = Double.valueOf(string);
180 }
181 catch (NumberFormatException ex) {
182 LogWriter.log( ex );
183 // suppress (value defaults to null)
184 }
185 break;
186 }
187 default:
188 // not a value, can't use it (defaults to null)
189 break;
190 }
191 clmList[column-2] = value;
192 setValue(value, columnKey, rowKey);
193
194 // Range 求め
195 if( value != null ) { // 4.0.0.0 (2007/11/28)
196 double dbl = value.doubleValue();
197 if( dbl < minimum ) { minimum = dbl; }
198 if( maximum < dbl ) { maximum = dbl; }
199 }
200 }
201 rowList.add( clmList );
202 }
203 numdata = rowList.toArray( new Number[columnCount-1][rowList.size()] );
204
205 range = new Range( minimum, maximum );
206 }
207 finally {
208 Closer.resultClose( resultSet );
209 Closer.stmtClose( statement );
210 }
211 }
212
213 /**
214 * ?された行?から、数字オブジェクトを取得します?
215 *
216 * @param row 行番号
217 * @param column カラ?号(列番号)
218 *
219 * @return ??行?の値
220 */
221 @Override
222 public Number getValue( final int row, final int column ) {
223 // 注意:行?の?が?す?
224 return numdata[column][row];
225 }
226
227 /**
228 * レンジオブジェクトを取得します?(独自メソ?)
229 *
230 * @return レンジオブジェク?
231 */
232 public Range getRange() {
233 return range;
234 }
235
236 /**
237 * こ???と?されたオブジェクトを比?ます?
238 *
239 * 親クラスで、equals メソ?が実?れて?ため、警告がでます?
240 *
241 * @og.rev 5.1.8.0 (2010/07/01) findbug対?
242 * @og.rev 5.1.9.0 (2010/08/01) findbug対?
243 *
244 * @param object 比?るオブジェク?
245 *
246 * @return Objectが等し??合? true、そ?な??合? false
247 */
248 @Override
249 public boolean equals( final Object object ) {
250 // return super.equals( object );
251 if( super.equals( object ) ) {
252 return hsCode == ((HybsJDBCCategoryDataset2)object).hsCode;
253 }
254 return false;
255 }
256
257 /**
258 * こ?オブジェクト?ハッシュコードを取得します?
259 *
260 * @og.rev 5.1.8.0 (2010/07/01) findbug対?
261 * @og.rev 5.1.9.0 (2010/08/01) findbug対?
262 *
263 * @return ハッシュコー?
264 */
265 // public int hashCode() { return super.hashCode() ; }
266 @Override
267 public int hashCode() { return hsCode ; }
268
269 /**
270 * こ?オブジェクトと?されたオブジェクトを比?ます?
271 *
272 * @og.rev 4.0.0.0 (2007/11/28) 新規追?
273 * @og.rev 4.3.5.0 (2009/02/01) 同?ブジェクトかど?の判定方法変更
274 * @og.rev 5.1.8.0 (2010/07/01) ?
275 *
276 * @param anObject Object 比?れるオブジェク?
277 *
278 * @return ?されたオブジェクトが等し??合? true、そ?な??合? false
279 */
280 // public boolean equals( final Object anObject ) {
281 // // if( anObject instanceof HybsJDBCCategoryDataset2 ) {
282 // // HybsJDBCCategoryDataset2 other = (HybsJDBCCategoryDataset2)anObject ;
283 // // return ( uniqNo == other.uniqNo ) ;
284 // // }
285 // // return false ;
286 //
287 // if( super.equals( anObject ) ) {
288 // HybsJDBCCategoryDataset2 other = ((HybsJDBCCategoryDataset2)anObject);
289 // if( numdata != null && numdata == other.numdata &&
290 // range != null && range.equals( other.range ) ) {
291 // return true;
292 // }
293 // }
294 // return false;
295 // }
296
297 /**
298 * こ?オブジェクト?ハッシュコードを返します?
299 *
300 * @og.rev 4.0.0.0 (2007/11/28) 新規追?
301 * @og.rev 4.3.5.0 (2009/02/01) ハッシュの求め方を変更
302 * @og.rev 5.1.8.0 (2010/07/01) ?
303 *
304 * @return こ?オブジェクト?ハッシュコード?
305 */
306 // public int hashCode() {
307 // // return uniqNo;
308 // return super.hashCode() +
309 // ((numdata == null) ? 0 : numdata.hashCode()) +
310 // ((range == null) ? 0 : range.hashCode()) ;
311 // }
312 }