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 java.sql.Connection;
019    // import java.sql.Date;
020    import java.sql.ResultSet;
021    import java.sql.ResultSetMetaData;
022    import java.sql.SQLException;
023    import java.sql.Statement;
024    // import java.sql.Types;
025    // import java.util.Locale;
026    
027    import org.opengion.fukurou.util.Closer;
028    import org.opengion.fukurou.util.LogWriter;
029    
030    import org.jfree.data.time.TimeSeriesCollection;
031    import org.jfree.data.time.TimeSeries;
032    import org.jfree.data.time.RegularTimePeriod;
033    // import org.jfree.data.time.Year;                             // Year  (int year) 
034    // import org.jfree.data.time.Month;                    // Month (int month, int year) 
035    // import org.jfree.data.time.Day;                              // Day   (int day, int month, int year)
036    // import org.jfree.data.time.Hour;                             // Hour  (int hour, int day, int month, int year)
037    // import org.jfree.data.time.Minute;                   // Minute(int minute, int hour, int day, int month, int year)
038    import org.jfree.data.time.Second;                      // Second(int second, int minute, int hour, int day, int month, int year) 
039    
040    /**
041     * HybsTimeSeriesCollection は、org.jfree.data.time.TimeSeriesCollection を継承したサブクラスで?
042     * オブジェクト作?とともに JDBC接続して、TimeSeries ??タを作?し?セ?します?
043     * TimeSeriesCollection は、XYDataset のサブクラスです?
044     *
045     * TimeSeriesLineV、TimeSeriesBarV、StackedTimeSeriesLineV の場合?縦持です?
046     *  ?.select series,x(時間),y(値) from XX order by series,x(時間) の縦持ちで、series のキーブレイク処?
047     * TimeSeriesLineH、TimeSeriesBarH、StackedTimeSeriesLineH の場合?横持です?
048     *  ?.select x(時間),y1(値),y2(値),・・・ from XX  order by x(時間) の横?
049     * series のキーブレイク処?れます?
050     *
051     * Stacked**** は、各シリーズのy(値)を?次??します??間で実績数をセ?し??時刻に
052     * どれだけ?来上がったかを表示するのに便利です?
053     *
054     * @og.rev 5.6.1.0 (2013/02/01) 新規作?
055     *
056     * @version  0.9.0  2001/05/05
057     * @author   Kazuhiko Hasegawa
058     * @since    JDK1.1,
059     */
060    public class HybsTimeSeriesCollection extends TimeSeriesCollection {
061            private static final long serialVersionUID = 561020130201L ;
062    
063            private final boolean vhFlag ;          // select? series を縦持V(true)か横持H(false)かを??
064            private final boolean isStacked ;       // ??タの???行うかど???  true:行う/false:行わな?
065    
066            /**
067             * チャートタイプを引数にとる?コンストラクター
068             *
069             * TimeSeriesLineV、TimeSeriesBarV、StackedTimeSeriesLineV の場合?縦持です?
070             *  ?.select series,x(時間),y(値) from XX order by series,x(時間) の縦持ちで、series のキーブレイク処?
071             * TimeSeriesLineH、TimeSeriesBarH、StackedTimeSeriesLineH の場合?横持です?
072             *  ?.select x(時間),y1(値),y2(値),・・・ from XX  order by x(時間) の横?
073             * series のキーブレイク処?れます?
074             *
075             * Stacked**** は、各シリーズのy(値)を?次??します??間で実績数をセ?し??時刻に
076             * どれだけ?来上がったかを表示するのに便利です?
077             *
078             * @param type  チャートタイ?
079             */
080            public HybsTimeSeriesCollection( final String type ) {
081                    super();
082                    vhFlag    = ( type.endsWith( "V" ) ) ;                          // V:縦?= true / H:横?= false
083                    isStacked = ( type.startsWith( "Stacked" ) ) ;          // Stacked:積み上げ = true
084            }
085    
086            /**
087             * HybsTimeSeriesCollection オブジェクト??に、DB検索結果の??タを設定します?
088             *
089             * こ?メソ?は、series の 縦?横持を、コンストラクターで判定して?す?
090             * TimeSeriesLineV、TimeSeriesBarV、StackedTimeSeriesLineV の場合?縦持です?
091             *  ?.select series,x(時間),y(値) from XX order by series,x(時間) の縦持ちで、series のキーブレイク処?
092             * TimeSeriesLineH、TimeSeriesBarH、StackedTimeSeriesLineH の場合?横持です?
093             *  ?.select x(時間),y1(値),y2(値),・・・ from XX  order by x(時間) の横?
094             * series のキーブレイク処?れます?
095             *
096             * @param con  the connection.
097             * @param query  the query.
098             *
099             */
100            public void executeQuery( final Connection con, final String query ) throws SQLException {
101                    if( vhFlag ) { innerQueryV( con,query ); }
102                    else             { innerQueryH( con,query ); }
103            }
104    
105            /**
106             * HybsTimeSeriesCollection オブジェクト??に、DB検索結果の??タを設定しま?縦??
107             * こ?メソ?が呼ばれるのは、TimeSeriesLineV、TimeSeriesBarV、StackedTimeSeriesLineV の場合です?
108             *
109             * こ?メソ?は、series の 縦持を想定して?す?
110             *  ?.select series,x(時間),y(値) from XX order by series,x(時間) の縦持ちで、series のキーブレイク処?
111             * series のキーブレイク処?れます?
112             *
113             * @param con  the connection.
114             * @param query  the query.
115             *
116             */
117            private void innerQueryV( final Connection con, final String query ) throws SQLException {
118    
119                    Statement statement = null;
120                    ResultSet resultSet = null;
121                    try {
122                            statement = con.createStatement();
123                            resultSet = statement.executeQuery(query);
124                            ResultSetMetaData metaData = resultSet.getMetaData();
125    
126                            int columnCount = metaData.getColumnCount();
127    
128                            if(columnCount < 3) {
129                                    String errMsg = "HybsTimeSeriesCollection.innerQueryV() : 実行できません?n"
130                                                            + "select series,x(時間),y(値) は、最低?です?それ以降?無視します?"
131                                                            + " SQL=" + query ;
132                                    throw new SQLException( errMsg );
133                            }
134    
135                            String bkSeries = null;         // キーブレイクのための過去のSeries
136                            double bkyn     = 0.0;
137    
138                            TimeSeries timeSeries = null;
139                            while (resultSet.next()) {
140                                    // first column contains the row key...
141                                    String seriVal  = resultSet.getString(1);                                               // 縦持ちの場合?、データの値がシリーズ名になる?
142                                    if( seriVal != null && !seriVal.equals( bkSeries ) ) {
143                                            if( timeSeries != null ) { addSeries( timeSeries ); }           // キーブレイクでセ?
144                                            timeSeries = new TimeSeries( seriVal );
145                                            bkSeries = seriVal ;
146                                            bkyn     = 0.0;
147                                    }
148    
149                                    String dateVal  = resultSet.getString(2);                       // x(時間)
150                                    RegularTimePeriod timep = getTimePeriod( dateVal );
151    
152                                    double yn = resultSet.getDouble(3);                                     // y(値)
153                                    bkyn = ( isStacked ) ? bkyn + yn : yn ;                         // isStacked = true の場合?、加算して?
154    
155                                    timeSeries.add( timep, bkyn );
156                            }
157                            if( timeSeries != null ) { addSeries( timeSeries ); }           // キーブレイクでセ?
158                    }
159                    finally {
160                            Closer.resultClose( resultSet ) ;
161                            Closer.stmtClose( statement ) ;
162                    }
163            }
164    
165            /**
166             * HybsTimeSeriesCollection オブジェクト??に、DB検索結果の??タを設定しま?横??
167             * こ?メソ?が呼ばれるのは、TimeSeriesLineH、TimeSeriesBarH、StackedTimeSeriesLineH の場合です?
168             *
169             * こ?メソ?は、series の 横持を想定して?す?
170             *  ?.select x(時間),y1(値),y2(値),・・・ from XX  order by x(時間) の横?
171             * で、y1, y2 ・・・ ?series として処?れます?
172             * series のラベルは、y1, y2 ・・・のカラ?になります?
173             *
174             * @param con  the connection.
175             * @param query  the query.
176             */
177            private void innerQueryH( final Connection con, final String query ) throws SQLException {
178    
179                    Statement statement = null;
180                    ResultSet resultSet = null;
181                    try {
182                            statement = con.createStatement();
183                            resultSet = statement.executeQuery(query);
184                            ResultSetMetaData metaData = resultSet.getMetaData();
185    
186                            int columnCount = metaData.getColumnCount();
187    
188                            if(columnCount < 2) {
189                                    String errMsg = "HybsTimeSeriesCollection.innerQueryH() : 実行できません?n"
190                                                            + "select x(時間),y1(値),y2(値) , ・・・・ は、最低?です?"
191                                                            + " SQL=" + query ;
192                                    throw new SQLException( errMsg );
193                            }
194    
195                            // ?リーズに対するカラ?イプを先に求めておく
196                            int seriSu = columnCount-1;                             // カラ?-1( x(時間) )
197                            TimeSeries[] timeSeries = new TimeSeries[seriSu];
198                            double[]     bkyn       = new double[seriSu];
199                            for( int j=0; j<seriSu; j++ ) {
200                                    timeSeries[j] = new TimeSeries( metaData.getColumnLabel(j+2) );         // 横持?場合?、カラ?をシリーズ名にする?
201                                    bkyn[j]       = 0.0;
202                            }
203    
204                            while (resultSet.next()) {
205                                    // first column contains the row key...
206                                    String dateVal  = resultSet.getString(1);                       // x(時間)
207                                    RegularTimePeriod timep = getTimePeriod( dateVal );
208    
209                                    for( int j=0; j<seriSu; j++ ) {
210                                            double yn = resultSet.getDouble(j+2);
211                                            bkyn[j] = ( isStacked ) ? bkyn[j] + yn : yn ;   // isStacked = true の場合?、加算して?
212                                            timeSeries[j].add( timep, bkyn[j] );
213                                    }
214                            }
215    
216                            for( int j=0; j<seriSu; j++ ) {
217                                    addSeries( timeSeries[j] );
218                            }
219                    }
220                    finally {
221                            Closer.resultClose( resultSet ) ;
222                            Closer.stmtClose( statement ) ;
223                    }
224            }
225    
226            /**
227             * 日付文字? から、RegularTimePeriodオブジェク?を生成します?
228             *
229             * こ?メソ?では、日付文字? として?yyyyMMdd" 形式と "yyyyMMddhhmmss" 形式?み認めて?す?
230             *  ?.8文字以上ある?合?yyyyMMdd 部??出して、年月日??を作?します?
231             *  ?.14文字以上ある?合?残りの、hhmmss 部??出して、時?情報を作?します?
232             *  ?.それ以外?場合??20100101000000" として、??ます?
233             *
234             * @param       dateVal 日付文字?(yyyyMMddhhmmss 形?
235             *
236             * @return      RegularTimePeriodオブジェク?Secondオブジェク?
237             */
238            private RegularTimePeriod getTimePeriod( final String dateVal ) {
239                    int second=0, minute=0, hour=0, day=1, month=1, year=2010 ;
240                    if( dateVal != null ) {
241                            if( dateVal.length() >= 8 ) {
242                                    year  = Integer.parseInt( dateVal.substring( 0,4 ) );
243                                    month = Integer.parseInt( dateVal.substring( 4,6 ) );
244                                    day   = Integer.parseInt( dateVal.substring( 6,8 ) );
245                            }
246                            if( dateVal.length() >= 14 ) {
247                                    hour   = Integer.parseInt( dateVal.substring( 8,10 ) );
248                                    minute = Integer.parseInt( dateVal.substring( 10,12 ) );
249                                    second = Integer.parseInt( dateVal.substring( 12,14 ) );
250                            }
251                    }
252    
253                    return new Second( second,minute,hour,day,month,year ) ;
254            }
255    
256    //      private Number getNumber( final Object objVal , final int columnType ) {
257    //              Number value = null;
258    //
259    //              switch (columnType) {
260    //                      case Types.TINYINT:
261    //                      case Types.SMALLINT:
262    //                      case Types.INTEGER:
263    //                      case Types.BIGINT:
264    //                      case Types.FLOAT:
265    //                      case Types.DOUBLE:
266    //                      case Types.DECIMAL:
267    //                      case Types.NUMERIC:
268    //                      case Types.REAL: {
269    //                              value = (Number)objVal;
270    //                              break;
271    //                      }
272    //                      case Types.DATE:
273    //                      case Types.TIME:
274    //                      case Types.TIMESTAMP: {
275    //                              Date date = (Date) objVal;
276    //                              value = Long.valueOf(date.getTime());
277    //                              break;
278    //                      }
279    //                      case Types.CHAR:
280    //                      case Types.VARCHAR:
281    //                      case Types.LONGVARCHAR: {
282    //                              String string = (String)objVal;
283    //                              try {
284    //                                      value = Double.valueOf(string);
285    //                              }
286    //                              catch (NumberFormatException ex) {
287    //      //                              LogWriter.log( ex );
288    //                                      // suppress (value defaults to null)
289    //                              }
290    //                              break;
291    //                      }
292    //                      default:
293    //                              // not a value, can't use it (defaults to null)
294    //                              break;
295    //              }
296    //              return value;
297    //      }
298    }