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 }